diff options
author | Steve Block <steveblock@google.com> | 2010-04-27 16:31:00 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-05-11 14:42:12 +0100 |
commit | dcc8cf2e65d1aa555cce12431a16547e66b469ee (patch) | |
tree | 92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/rendering | |
parent | ccac38a6b48843126402088a309597e682f40fe6 (diff) | |
download | external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2 |
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/rendering')
134 files changed, 4457 insertions, 1890 deletions
diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp index 6ec3195..6f25861 100644 --- a/WebCore/rendering/EllipsisBox.cpp +++ b/WebCore/rendering/EllipsisBox.cpp @@ -36,8 +36,8 @@ void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) context->setFillColor(textColor, style->colorSpace()); bool setShadow = false; if (style->textShadow()) { - context->setShadow(IntSize(style->textShadow()->x, style->textShadow()->y), - style->textShadow()->blur, style->textShadow()->color, style->colorSpace()); + context->setShadow(IntSize(style->textShadow()->x(), style->textShadow()->y()), + style->textShadow()->blur(), style->textShadow()->color(), style->colorSpace()); setShadow = true; } diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index 34eec30..6ee610d 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -21,6 +21,7 @@ #include "InlineFlowBox.h" #include "CachedImage.h" +#include "CSSPropertyNames.h" #include "Document.h" #include "EllipsisBox.h" #include "GraphicsContext.h" @@ -165,7 +166,7 @@ void InlineFlowBox::attachLineBoxToRenderObject() void InlineFlowBox::adjustPosition(int dx, int dy) { - InlineRunBox::adjustPosition(dx, dy); + InlineBox::adjustPosition(dx, dy); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) child->adjustPosition(dx, dy); if (m_overflow) @@ -288,14 +289,16 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, bool& needsWordSpacing) int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing()); rightLayoutOverflow = max(xPos + text->width() - letterSpacing, rightLayoutOverflow); - int leftGlyphOverflow = -strokeOverflow; - int rightGlyphOverflow = strokeOverflow - letterSpacing; + GlyphOverflow* glyphOverflow = static_cast<InlineTextBox*>(curr)->glyphOverflow(); + + int leftGlyphOverflow = -strokeOverflow - (glyphOverflow ? glyphOverflow->left : 0); + int rightGlyphOverflow = strokeOverflow - letterSpacing + (glyphOverflow ? glyphOverflow->right : 0); int childOverflowLeft = leftGlyphOverflow; int childOverflowRight = rightGlyphOverflow; - for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) { - childOverflowLeft = min(childOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow); - childOverflowRight = max(childOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow); + for (const ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next()) { + childOverflowLeft = min(childOverflowLeft, shadow->x() - shadow->blur() + leftGlyphOverflow); + childOverflowRight = max(childOverflowRight, shadow->x() + shadow->blur() + rightGlyphOverflow); } leftVisualOverflow = min(xPos + childOverflowLeft, leftVisualOverflow); @@ -412,35 +415,35 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi int lineHeight; int baseline; - Vector<const SimpleFontData*> usedFonts; + Vector<const SimpleFontData*>* usedFonts = 0; if (curr->isInlineTextBox()) - static_cast<InlineTextBox*>(curr)->takeFallbackFonts(usedFonts); + usedFonts = static_cast<InlineTextBox*>(curr)->fallbackFonts(); - if (!usedFonts.isEmpty()) { - usedFonts.append(curr->renderer()->style(m_firstLine)->font().primaryFont()); + if (usedFonts) { + 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[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts[i]->ascent()); - baselineToBottom = max(baselineToBottom, usedFonts[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent() - halfLeading); + 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[i]->ascent() - usedFonts[i]->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts[i]->ascent()); + 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[i]->ascent() - usedFonts[i]->descent()) / 2; - baseline = max(baseline, halfLeading + usedFonts[i]->ascent()); + 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 { @@ -562,15 +565,17 @@ void InlineFlowBox::computeVerticalOverflow(int lineTop, int lineBottom, bool st continue; int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); - - int topGlyphOverflow = -strokeOverflow; - int bottomGlyphOverflow = strokeOverflow; - + + GlyphOverflow* glyphOverflow = static_cast<InlineTextBox*>(curr)->glyphOverflow(); + + int topGlyphOverflow = -strokeOverflow - (glyphOverflow ? glyphOverflow->top : 0); + int bottomGlyphOverflow = strokeOverflow + (glyphOverflow ? glyphOverflow->bottom : 0); + int childOverflowTop = topGlyphOverflow; int childOverflowBottom = bottomGlyphOverflow; - for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) { - childOverflowTop = min(childOverflowTop, shadow->y - shadow->blur + topGlyphOverflow); - childOverflowBottom = max(childOverflowBottom, shadow->y + shadow->blur + bottomGlyphOverflow); + for (const ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next()) { + childOverflowTop = min(childOverflowTop, shadow->y() - shadow->blur() + topGlyphOverflow); + childOverflowBottom = max(childOverflowBottom, shadow->y() + shadow->blur() + bottomGlyphOverflow); } topVisualOverflow = min(curr->y() + childOverflowTop, topVisualOverflow); @@ -703,11 +708,11 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right, // but it isn't even clear how this should work at all. int xOffsetOnLine = 0; - for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) + for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) xOffsetOnLine += curr->width(); int startX = tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; - for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); paintInfo.context->save(); paintInfo.context->clip(IntRect(tx, ty, width(), height())); @@ -760,7 +765,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int if (styleToUse->boxShadow()) paintBoxShadow(context, styleToUse, Normal, tx, ty, w, h); - Color c = styleToUse->backgroundColor(); + Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor); paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), tx, ty, w, h); if (styleToUse->boxShadow()) @@ -788,11 +793,11 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right, // but it isn't even clear how this should work at all. int xOffsetOnLine = 0; - for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) + for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) xOffsetOnLine += curr->width(); int startX = tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; - for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); context->save(); context->clip(IntRect(tx, ty, w, h)); @@ -859,11 +864,11 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty // We have a mask image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. int xOffsetOnLine = 0; - for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) + for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) xOffsetOnLine += curr->width(); int startX = tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; - for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); paintInfo.context->save(); paintInfo.context->clip(IntRect(tx, ty, w, h)); @@ -957,7 +962,7 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int tx += borderLeft() + paddingLeft(); Color underline, overline, linethrough; - underline = overline = linethrough = styleToUse->color(); + underline = overline = linethrough = styleToUse->visitedDependentColor(CSSPropertyColor); if (!parent()) renderer()->getTextDecorationColors(deco, underline, overline, linethrough); @@ -976,15 +981,15 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int bool setClip = false; int extraOffset = 0; - ShadowData* shadow = styleToUse->textShadow(); - if (!linesAreOpaque && shadow && shadow->next) { + const ShadowData* shadow = styleToUse->textShadow(); + if (!linesAreOpaque && shadow && shadow->next()) { IntRect clipRect(tx, ty, w, baselinePos + 2); - for (ShadowData* s = shadow; s; s = s->next) { + for (const ShadowData* s = shadow; s; s = s->next()) { IntRect shadowRect(tx, ty, w, baselinePos + 2); - shadowRect.inflate(s->blur); - shadowRect.move(s->x, s->y); + shadowRect.inflate(s->blur()); + shadowRect.move(s->x(), s->y()); clipRect.unite(shadowRect); - extraOffset = max(extraOffset, max(0, s->y) + s->blur); + extraOffset = max(extraOffset, max(0, s->y()) + s->blur()); } context->save(); context->clip(clipRect); @@ -997,14 +1002,14 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int bool setShadow = false; do { if (shadow) { - if (!shadow->next) { + if (!shadow->next()) { // The last set of lines paints normally inside the clip. ty -= extraOffset; extraOffset = 0; } - context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color, colorSpace); + context->setShadow(IntSize(shadow->x(), shadow->y() - extraOffset), shadow->blur(), shadow->color(), colorSpace); setShadow = true; - shadow = shadow->next; + shadow = shadow->next(); } if (paintUnderline) { diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h index 23b5cc9..ecb4724 100644 --- a/WebCore/rendering/InlineFlowBox.h +++ b/WebCore/rendering/InlineFlowBox.h @@ -21,7 +21,7 @@ #ifndef InlineFlowBox_h #define InlineFlowBox_h -#include "InlineRunBox.h" +#include "InlineBox.h" #include "RenderOverflow.h" namespace WebCore { @@ -30,12 +30,14 @@ class HitTestRequest; class HitTestResult; class RenderLineBoxList; -class InlineFlowBox : public InlineRunBox { +class InlineFlowBox : public InlineBox { public: InlineFlowBox(RenderObject* obj) - : InlineRunBox(obj) + : InlineBox(obj) , m_firstChild(0) , m_lastChild(0) + , m_prevLineBox(0) + , m_nextLineBox(0) , m_includeLeftEdge(false) , m_includeRightEdge(false) #ifndef NDEBUG @@ -54,8 +56,10 @@ public: virtual ~InlineFlowBox(); #endif - InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); } - InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); } + InlineFlowBox* prevLineBox() const { return m_prevLineBox; } + InlineFlowBox* nextLineBox() const { return m_nextLineBox; } + void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; } + void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; } InlineBox* firstChild() const { checkConsistency(); return m_firstChild; } InlineBox* lastChild() const { checkConsistency(); return m_lastChild; } @@ -164,12 +168,14 @@ public: protected: OwnPtr<RenderOverflow> m_overflow; -private: virtual bool isInlineFlowBox() const { return true; } InlineBox* m_firstChild; InlineBox* m_lastChild; + InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject + InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject + bool m_includeLeftEdge : 1; bool m_includeRightEdge : 1; bool m_hasTextChildren : 1; diff --git a/WebCore/rendering/InlineRunBox.h b/WebCore/rendering/InlineRunBox.h deleted file mode 100644 index cbc82d5..0000000 --- a/WebCore/rendering/InlineRunBox.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2003, 2006 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef InlineRunBox_h -#define InlineRunBox_h - -#include "InlineBox.h" - -namespace WebCore { - -class InlineRunBox : public InlineBox { -public: - InlineRunBox(RenderObject* obj) - : InlineBox(obj) - , m_prevLine(0) - , m_nextLine(0) - { - } - - InlineRunBox* prevLineBox() const { return m_prevLine; } - InlineRunBox* nextLineBox() const { return m_nextLine; } - void setNextLineBox(InlineRunBox* n) { m_nextLine = n; } - void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; } - - virtual void paintBoxDecorations(RenderObject::PaintInfo&, int /*tx*/, int /*ty*/) { } - virtual void paintTextDecorations(RenderObject::PaintInfo&, int /*tx*/, int /*ty*/, bool /*paintedChildren*/ = false) { } - -protected: - InlineRunBox* m_prevLine; // The previous box that also uses our RenderObject - InlineRunBox* m_nextLine; // The next box that also uses our RenderObject -}; - -} // namespace WebCore - -#endif // InlineRunBox_h diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 9f17b0c..9c28b42 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -273,7 +273,7 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in return false; } -static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked) +static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, int x, int y, int w, int h, const ShadowData* shadow, bool stroked) { Color fillColor = context->fillColor(); ColorSpace fillColorSpace = context->fillColorSpace(); @@ -285,11 +285,11 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con IntSize extraOffset; if (shadow) { - IntSize shadowOffset(shadow->x, shadow->y); - int shadowBlur = shadow->blur; - const Color& shadowColor = shadow->color; + IntSize shadowOffset(shadow->x(), shadow->y()); + int shadowBlur = shadow->blur(); + const Color& shadowColor = shadow->color(); - if (shadow->next || stroked || !opaque) { + if (shadow->next() || stroked || !opaque) { IntRect shadowRect(x, y, w, h); shadowRect.inflate(shadowBlur); shadowRect.move(shadowOffset); @@ -315,12 +315,12 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con if (!shadow) break; - if (shadow->next || stroked || !opaque) + if (shadow->next() || stroked || !opaque) context->restore(); else context->clearShadow(); - shadow = shadow->next; + shadow = shadow->next(); } while (shadow || stroked || !opaque); } @@ -405,24 +405,20 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) Color textFillColor; Color textStrokeColor; float textStrokeWidth = styleToUse->textStrokeWidth(); - ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow(); + const ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow(); if (paintInfo.forceBlackText) { textFillColor = Color::black; textStrokeColor = Color::black; } else { - textFillColor = styleToUse->textFillColor(); - if (!textFillColor.isValid()) - textFillColor = styleToUse->color(); - + textFillColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextFillColor); + // Make the text fill color legible against a white background if (styleToUse->forceBackgroundsToWhite()) textFillColor = correctedTextColor(textFillColor, Color::white); - textStrokeColor = styleToUse->textStrokeColor(); - if (!textStrokeColor.isValid()) - textStrokeColor = styleToUse->color(); - + textStrokeColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextStrokeColor); + // Make the text stroke color legible against a white background if (styleToUse->forceBackgroundsToWhite()) textStrokeColor = correctedTextColor(textStrokeColor, Color::white); @@ -434,7 +430,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) Color selectionFillColor = textFillColor; Color selectionStrokeColor = textStrokeColor; float selectionStrokeWidth = textStrokeWidth; - ShadowData* selectionShadow = textShadow; + const ShadowData* selectionShadow = textShadow; if (haveSelection) { // Check foreground color first. Color foreground = paintInfo.forceBlackText ? Color::black : renderer()->selectionForegroundColor(); @@ -445,7 +441,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) } if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) { - ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow(); + const ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow(); if (shadow != selectionShadow) { if (!paintSelectedTextOnly) paintSelectedTextSeparately = true; @@ -517,7 +513,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) // Paint decorations if (d != TDNONE && paintInfo.phase != PaintPhaseSelection && styleToUse->htmlHacks()) { - context->setStrokeColor(styleToUse->color(), styleToUse->colorSpace()); + context->setStrokeColor(styleToUse->visitedDependentColor(CSSPropertyColor), styleToUse->colorSpace()); paintDecoration(context, tx, ty, d, textShadow); } @@ -577,7 +573,7 @@ void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, Ren if (sPos >= ePos) return; - Color textColor = style->color(); + Color textColor = style->visitedDependentColor(CSSPropertyColor); Color c = renderer()->selectionBackgroundColor(); if (!c.isValid() || c.alpha() == 0) return; @@ -644,7 +640,7 @@ void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& typ #endif -void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, int deco, ShadowData* shadow) +void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, int deco, const ShadowData* shadow) { tx += m_x; ty += m_y; @@ -673,15 +669,15 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in bool setClip = false; int extraOffset = 0; - if (!linesAreOpaque && shadow && shadow->next) { + if (!linesAreOpaque && shadow && shadow->next()) { context->save(); IntRect clipRect(tx, ty, width, baseline + 2); - for (ShadowData* s = shadow; s; s = s->next) { + for (const ShadowData* s = shadow; s; s = s->next()) { IntRect shadowRect(tx, ty, width, baseline + 2); - shadowRect.inflate(s->blur); - shadowRect.move(s->x, s->y); + shadowRect.inflate(s->blur()); + shadowRect.move(s->x(), s->y()); clipRect.unite(shadowRect); - extraOffset = max(extraOffset, max(0, s->y) + s->blur); + extraOffset = max(extraOffset, max(0, s->y()) + s->blur()); } context->save(); context->clip(clipRect); @@ -695,14 +691,14 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in do { if (shadow) { - if (!shadow->next) { + if (!shadow->next()) { // The last set of lines paints normally inside the clip. ty -= extraOffset; extraOffset = 0; } - context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color, colorSpace); + context->setShadow(IntSize(shadow->x(), shadow->y() - extraOffset), shadow->blur(), shadow->color(), colorSpace); setShadow = true; - shadow = shadow->next; + shadow = shadow->next(); } if (deco & UNDERLINE) { @@ -1029,30 +1025,48 @@ bool InlineTextBox::containsCaretOffset(int offset) const return true; } -typedef HashMap<InlineTextBox*, Vector<const SimpleFontData*> > FallbackFontsMap; -static FallbackFontsMap* gFallbackFontsMap; - void InlineTextBox::setFallbackFonts(const HashSet<const SimpleFontData*>& fallbackFonts) { - if (!gFallbackFontsMap) - gFallbackFontsMap = new FallbackFontsMap; + if (!s_glyphOverflowAndFallbackFontsMap) + s_glyphOverflowAndFallbackFontsMap = new GlyphOverflowAndFallbackFontsMap; - FallbackFontsMap::iterator it = gFallbackFontsMap->set(this, Vector<const SimpleFontData*>()).first; - ASSERT(it->second.isEmpty()); - copyToVector(fallbackFonts, it->second); + GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->add(this, make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first; + ASSERT(it->second.first.isEmpty()); + copyToVector(fallbackFonts, it->second.first); } -void InlineTextBox::takeFallbackFonts(Vector<const SimpleFontData*>& fallbackFonts) +Vector<const SimpleFontData*>* InlineTextBox::fallbackFonts() const { - if (!gFallbackFontsMap) - return; + if (!s_glyphOverflowAndFallbackFontsMap) + return 0; - FallbackFontsMap::iterator it = gFallbackFontsMap->find(this); - if (it == gFallbackFontsMap->end()) - return; + GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->find(this); + if (it == s_glyphOverflowAndFallbackFontsMap->end()) + return 0; + + return &it->second.first; +} + +InlineTextBox::GlyphOverflowAndFallbackFontsMap* InlineTextBox::s_glyphOverflowAndFallbackFontsMap = 0; + +void InlineTextBox::setGlyphOverflow(const GlyphOverflow& glyphOverflow) +{ + if (!s_glyphOverflowAndFallbackFontsMap) + s_glyphOverflowAndFallbackFontsMap = new GlyphOverflowAndFallbackFontsMap; + + GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->add(this, make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first; + it->second.second = glyphOverflow; +} + +GlyphOverflow* InlineTextBox::glyphOverflow() const +{ + if (!s_glyphOverflowAndFallbackFontsMap) + return 0; + GlyphOverflowAndFallbackFontsMap::iterator it = s_glyphOverflowAndFallbackFontsMap->find(this); + if (it == s_glyphOverflowAndFallbackFontsMap->end()) + return 0; - fallbackFonts.swap(it->second); - gFallbackFontsMap->remove(it); + return &it->second.second; } } // namespace WebCore diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index 0a83ddd..2eb0c42 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -23,7 +23,7 @@ #ifndef InlineTextBox_h #define InlineTextBox_h -#include "InlineRunBox.h" +#include "InlineBox.h" #include "RenderText.h" // so textRenderer() can be inline namespace WebCore { @@ -37,18 +37,22 @@ const unsigned short cFullTruncation = USHRT_MAX - 1; void updateGraphicsContext(GraphicsContext*, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace); Color correctedTextColor(Color textColor, Color backgroundColor); -class InlineTextBox : public InlineRunBox { +class InlineTextBox : public InlineBox { public: InlineTextBox(RenderObject* obj) - : InlineRunBox(obj) + : InlineBox(obj) + , m_prevTextBox(0) + , m_nextTextBox(0) , m_start(0) , m_len(0) , m_truncation(cNoTruncation) { } - InlineTextBox* nextTextBox() const { return static_cast<InlineTextBox*>(nextLineBox()); } - InlineTextBox* prevTextBox() const { return static_cast<InlineTextBox*>(prevLineBox()); } + InlineTextBox* prevTextBox() const { return m_prevTextBox; } + InlineTextBox* nextTextBox() const { return m_nextTextBox; } + void setNextTextBox(InlineTextBox* n) { m_nextTextBox = n; } + void setPreviousTextBox(InlineTextBox* p) { m_prevTextBox = p; } unsigned start() const { return m_start; } unsigned end() const { return m_len ? m_start + m_len - 1 : m_start; } @@ -60,7 +64,16 @@ public: void offsetRun(int d) { m_start += d; } void setFallbackFonts(const HashSet<const SimpleFontData*>&); - void takeFallbackFonts(Vector<const SimpleFontData*>&); + Vector<const SimpleFontData*>* fallbackFonts() const; + + void setGlyphOverflow(const GlyphOverflow&); + GlyphOverflow* glyphOverflow() const; + + static void clearGlyphOverflowAndFallbackFontMap() + { + if (s_glyphOverflowAndFallbackFontsMap) + s_glyphOverflowAndFallbackFontsMap->clear(); + } unsigned short truncation() { return m_truncation; } @@ -116,12 +129,18 @@ public: bool containsCaretOffset(int offset) const; // false for offset after line break private: + InlineTextBox* m_prevTextBox; // The previous box that also uses our RenderObject + InlineTextBox* m_nextTextBox; // The next box that also uses our RenderObject + int m_start; unsigned short m_len; unsigned short m_truncation; // Where to truncate when text overflow is applied. We use special constants to // denote no truncation (the whole run paints) and full truncation (nothing paints at all). + typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap; + static GlyphOverflowAndFallbackFontsMap* s_glyphOverflowAndFallbackFontsMap; + protected: void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, int startPos, int endPos); void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, bool background); @@ -131,7 +150,7 @@ protected: #endif private: - void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, ShadowData*); + void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, const ShadowData*); void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&); void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, const DocumentMarker&, RenderStyle*, const Font&, bool grammar); void paintTextMatchMarker(GraphicsContext*, int tx, int ty, const DocumentMarker&, RenderStyle*, const Font&); diff --git a/WebCore/rendering/LayoutState.cpp b/WebCore/rendering/LayoutState.cpp index 883f74d..c94e77b 100644 --- a/WebCore/rendering/LayoutState.cpp +++ b/WebCore/rendering/LayoutState.cpp @@ -62,20 +62,17 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& m_clipped = !fixed && prev->m_clipped; if (m_clipped) m_clipRect = prev->m_clipRect; + if (renderer->hasOverflowClip()) { - int x = m_offset.width(); - int y = m_offset.height(); RenderLayer* layer = renderer->layer(); - IntRect clipRect(x, y, layer->width(), layer->height()); - clipRect.move(renderer->view()->layoutDelta()); + IntRect clipRect(toPoint(m_offset) + renderer->view()->layoutDelta(), layer->size()); if (m_clipped) m_clipRect.intersect(clipRect); else { m_clipRect = clipRect; m_clipped = true; } - layer->subtractScrolledContentOffset(x, y); - m_offset = IntSize(x, y); + m_offset -= layer->scrolledContentOffset(); } m_layoutDelta = m_next->m_layoutDelta; diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 2b7a8c8..569f214 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -615,6 +615,9 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event) if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) return; + if (!attached()) + return; + if (event->type() == eventNames().mousedownEvent) m_mediaElement->beginScrubbing(); @@ -660,6 +663,9 @@ void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) return; + if (!attached()) + return; + MediaControlInputElement::defaultEventHandler(event); if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 62e177d..3f53456 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -187,7 +187,7 @@ void RenderBlock::destroy() // that will outlast this block. In the non-anonymous block case those // children will be destroyed by the time we return from this function. if (isAnonymousBlock()) { - for (InlineFlowBox* box = firstLineBox(); box; box = box->nextFlowBox()) { + for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) { while (InlineBox* childBox = box->firstChild()) childBox->remove(); } @@ -265,8 +265,14 @@ void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId) void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) { // Make sure we don't append things after :after-generated content if we have it. - if (!beforeChild && isAfterContent(lastChild())) - beforeChild = lastChild(); + if (!beforeChild) { + RenderObject* lastRenderer = lastChild(); + + if (isAfterContent(lastRenderer)) + beforeChild = lastRenderer; + else if (lastRenderer && lastRenderer->isAnonymousBlock() && isAfterContent(lastRenderer->lastChild())) + beforeChild = lastRenderer->lastChild(); + } bool madeBoxesNonInline = false; @@ -786,8 +792,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren) if (previousHeight != height()) relayoutChildren = true; - // It's weird that we're treating float information as normal flow overflow, but we do this because floatRect() isn't - // able to be propagated up the render tree yet. Overflow information is however. This check is designed to catch anyone + // This check is designed to catch anyone // who wasn't going to propagate float information up to the parent and yet could potentially be painted by its ancestor. if (isRoot() || expandsToEncloseOverhangingFloats()) addOverflowFromFloats(); @@ -827,11 +832,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren) if (hasOverflowClip()) { // Adjust repaint rect for scroll offset - int x = repaintRect.x(); - int y = repaintRect.y(); - layer()->subtractScrolledContentOffset(x, y); - repaintRect.setX(x); - repaintRect.setY(y); + repaintRect.move(-layer()->scrolledContentOffset()); // Don't allow this rect to spill out of our overflow box. repaintRect.intersect(IntRect(0, 0, width(), height())); @@ -1568,7 +1569,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty) void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty) { - const Color& ruleColor = style()->columnRuleColor(); + const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor); bool ruleTransparent = style()->columnRuleIsTransparent(); EBorderStyle ruleStyle = style()->columnRuleStyle(); int ruleWidth = style()->columnRuleWidth(); @@ -1603,7 +1604,7 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty) int ruleTop = ty + borderTop() + paddingTop(); int ruleBottom = ruleTop + contentHeight(); drawLineForBoxSide(paintInfo.context, ruleStart, ruleTop, ruleEnd, ruleBottom, - style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0); + style()->direction() == LTR ? BSLeft : BSRight, ruleColor, ruleStyle, 0, 0); } ruleX = currXOffset; @@ -1680,16 +1681,15 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { // Check for page-break-before: always, and if it's set, break and bail. - if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS && - inRootBlockContext() && (ty + child->y()) > paintInfo.rect.y() && - (ty + child->y()) < paintInfo.rect.bottom()) { + if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS + && (ty + child->y()) > paintInfo.rect.y() + && (ty + child->y()) < paintInfo.rect.bottom()) { view()->setBestTruncatedAt(ty + child->y(), this, true); return; } // Check for page-break-inside: avoid, and it it's set, break and bail. if (isPrinting && !childrenInline() && child->style()->pageBreakInside() == PBAVOID - && inRootBlockContext() && ty + child->y() > paintInfo.rect.y() && ty + child->y() < paintInfo.rect.bottom() && ty + child->y() + child->height() > paintInfo.rect.bottom()) { @@ -1701,9 +1701,9 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) child->paint(info, tx, ty); // Check for page-break-after: always, and if it's set, break and bail. - if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS && - inRootBlockContext() && (ty + child->y() + child->height()) > paintInfo.rect.y() && - (ty + child->y() + child->height()) < paintInfo.rect.bottom()) { + if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS + && (ty + child->y() + child->height()) > paintInfo.rect.y() + && (ty + child->y() + child->height()) < paintInfo.rect.bottom()) { view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginBottom()), this, true); return; } @@ -1750,11 +1750,14 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty) if (paintPhase == PaintPhaseBlockBackground) return; - // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s + // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div). int scrolledX = tx; int scrolledY = ty; - if (hasOverflowClip()) - layer()->subtractScrolledContentOffset(scrolledX, scrolledY); + if (hasOverflowClip()) { + IntSize offset = layer()->scrolledContentOffset(); + scrolledX -= offset.width(); + scrolledY -= offset.height(); + } // 2. paint contents if (paintPhase != PaintPhaseSelfOutline) { @@ -1780,7 +1783,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty) // 5. paint outline. if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE) - paintOutline(paintInfo.context, tx, ty, width(), height(), style()); + paintOutline(paintInfo.context, tx, ty, width(), height()); // 6. paint continuation outlines. if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) { @@ -1966,18 +1969,16 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC // FIXME: this is broken with transforms TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); mapLocalToContainer(repaintContainer, false, false, transformState); - FloatPoint offsetFromRepaintContainer = transformState.mappedPoint(); - int x = offsetFromRepaintContainer.x(); - int y = offsetFromRepaintContainer.y(); + IntPoint offsetFromRepaintContainer = roundedIntPoint(transformState.mappedPoint()); if (hasOverflowClip()) - layer()->subtractScrolledContentOffset(x, y); + offsetFromRepaintContainer -= layer()->scrolledContentOffset(); int lastTop = 0; int lastLeft = leftSelectionOffset(this, lastTop); int lastRight = rightSelectionOffset(this, lastTop); - return fillSelectionGaps(this, x, y, x, y, lastTop, lastLeft, lastRight); + return fillSelectionGaps(this, offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), lastTop, lastLeft, lastRight); } void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) @@ -2380,8 +2381,14 @@ void RenderBlock::removeFloatingObject(RenderBox* o) DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); while (it.current()) { if (it.current()->m_renderer == o) { - if (childrenInline()) - markLinesDirtyInVerticalRange(0, it.current()->m_bottom); + if (childrenInline()) { + int bottom = it.current()->m_bottom; + // Special-case zero- and less-than-zero-height floats: those don't touch + // the line that they're on, but it still needs to be dirtied. This is + // accomplished by pretending they have a height of 1. + bottom = max(bottom, it.current()->m_top + 1); + markLinesDirtyInVerticalRange(0, bottom); + } m_floatingObjects->removeRef(it.current()); } ++it; @@ -2660,24 +2667,6 @@ RenderBlock::floatBottom() const return bottom; } -IntRect RenderBlock::floatRect() const -{ - IntRect result; - if (!m_floatingObjects || hasOverflowClip() || hasColumns()) - return result; - FloatingObject* r; - DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for (; (r = it.current()); ++it) { - if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) { - IntRect childRect = r->m_renderer->visibleOverflowRect(); - childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop()); - result.unite(childRect); - } - } - - return result; -} - int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const { int bottom = includeSelf && width() > 0 ? height() : 0; @@ -2846,7 +2835,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel if (!includeSelf) { right = max(right, borderLeft() + paddingLeft() + paddingRight() + relativeOffset); if (childrenInline()) { - for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) { + for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) { int childRightEdge = currBox->x() + currBox->width(); // If this node is a root editable element, then the rightmostPosition should account for a caret at the end. @@ -2941,7 +2930,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf } if (!includeSelf && firstLineBox()) { - for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) + for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) left = min(left, (int)currBox->x() + relativeOffset); } @@ -3050,8 +3039,8 @@ void RenderBlock::clearFloats() addIntrudingFloats(block, xoffset, offset); if (childrenInline()) { - int changeTop = INT_MAX; - int changeBottom = INT_MIN; + int changeTop = numeric_limits<int>::max(); + int changeBottom = numeric_limits<int>::min(); if (m_floatingObjects) { for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) { FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer); @@ -3228,6 +3217,32 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove } } +int RenderBlock::visibleTopOfHighestFloatExtendingBelow(int bottom, int maxHeight) const +{ + int top = bottom; + if (m_floatingObjects) { + FloatingObject* floatingObject; + for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); (floatingObject = it.current()); ++it) { + RenderBox* floatingBox = floatingObject->m_renderer; + IntRect visibleOverflow = floatingBox->visibleOverflowRect(); + visibleOverflow.move(floatingBox->x(), floatingBox->y()); + if (visibleOverflow.y() < top && visibleOverflow.bottom() > bottom && visibleOverflow.height() <= maxHeight && floatingBox->containingBlock() == this) + top = visibleOverflow.y(); + } + } + + if (!childrenInline()) { + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + if (child->isFloatingOrPositioned() || !child->isRenderBlock()) + continue; + RenderBlock* childBlock = toRenderBlock(child); + top = min(top, childBlock->y() + childBlock->visibleTopOfHighestFloatExtendingBelow(bottom - childBlock->y(), maxHeight)); + } + } + + return top; +} + int RenderBlock::getClearDelta(RenderBox* child, int yPos) { // There is no need to compute clearance if we have no floats. @@ -3319,8 +3334,11 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu // Hit test descendants first. int scrolledX = tx; int scrolledY = ty; - if (hasOverflowClip()) - layer()->subtractScrolledContentOffset(scrolledX, scrolledY); + if (hasOverflowClip()) { + IntSize offset = layer()->scrolledContentOffset(); + scrolledX -= offset.width(); + scrolledY -= offset.height(); + } // Hit test contents if we don't have columns. if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction)) @@ -3595,15 +3613,16 @@ VisiblePosition RenderBlock::positionForPoint(const IntPoint& point) void RenderBlock::offsetForContents(int& tx, int& ty) const { + IntPoint contentsPoint(tx, ty); + if (hasOverflowClip()) - layer()->addScrolledContentOffset(tx, ty); + contentsPoint += layer()->scrolledContentOffset(); - if (hasColumns()) { - IntPoint contentsPoint(tx, ty); + if (hasColumns()) adjustPointToColumnContents(contentsPoint); - tx = contentsPoint.x(); - ty = contentsPoint.y(); - } + + tx = contentsPoint.x(); + ty = contentsPoint.y(); } int RenderBlock::availableWidth() const @@ -3765,11 +3784,13 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight) // This represents the real column position. IntRect colRect(currX, top, desiredColumnWidth, colHeight); - + + int truncationPoint = visibleTopOfHighestFloatExtendingBelow(currY + colHeight, colHeight); + // For the simulated paint, we pretend like everything is in one long strip. - IntRect pageRect(left, currY, desiredColumnWidth, colHeight); + IntRect pageRect(left, currY, desiredColumnWidth, truncationPoint - currY); v->setPrintRect(pageRect); - v->setTruncatedAt(currY + colHeight); + v->setTruncatedAt(truncationPoint); GraphicsContext context((PlatformGraphicsContext*)0); RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0); @@ -3784,7 +3805,7 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight) int adjustedBottom = v->bestTruncatedAt(); if (adjustedBottom <= currY) - adjustedBottom = currY + colHeight; + adjustedBottom = truncationPoint; colRect.setHeight(adjustedBottom - currY); @@ -3859,8 +3880,20 @@ void RenderBlock::adjustPointToColumnContents(IntPoint& point) const // Add in half the column gap to the left and right of the rect. IntRect colRect = colRects->at(i); IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height()); - - if (gapAndColumnRect.contains(point)) { + + if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRect.right()) { + // FIXME: The clamping that follows is not completely right for right-to-left + // content. + // Clamp everything above the column to its top left. + if (point.y() < gapAndColumnRect.y()) + point = gapAndColumnRect.location(); + // Clamp everything below the column to the next column's top left. If there is + // no next column, this still maps to just after this column. + else if (point.y() >= gapAndColumnRect.bottom()) { + point = gapAndColumnRect.location(); + point.move(0, gapAndColumnRect.height()); + } + // We're inside the column. Translate the x and y into our column coordinate space. point.move(columnPoint.x() - colRect.x(), yOffset); return; @@ -4635,7 +4668,7 @@ void RenderBlock::updateFirstLetter() // Drill into inlines looking for our first text child. RenderObject* currChild = firstLetterBlock->firstChild(); - while (currChild && currChild->needsLayout() && (!currChild->isReplaced() || currChild->isFloatingOrPositioned()) && !currChild->isText()) { + while (currChild && currChild->needsLayout() && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) { if (currChild->isFloatingOrPositioned()) { if (currChild->style()->styleType() == FIRST_LETTER) break; @@ -4722,9 +4755,7 @@ void RenderBlock::updateFirstLetter() // construct text fragment for the first letter RenderTextFragment* letter = new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length); - RefPtr<RenderStyle> newStyle = RenderStyle::create(); - newStyle->inheritFrom(pseudoStyle); - letter->setStyle(newStyle.release()); + letter->setStyle(pseudoStyle); firstLetter->addChild(letter); textObj->destroy(); @@ -4733,17 +4764,6 @@ void RenderBlock::updateFirstLetter() } } -bool RenderBlock::inRootBlockContext() const -{ - if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip()) - return false; - - if (isRoot() || isRenderView()) - return true; - - return containingBlock()->inRootBlockContext(); -} - // Helper methods for obtaining the last line, computing line counts and heights for line counts // (crawling into blocks). static bool shouldCheckLines(RenderObject* obj) diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index c1f8dde..751a1df 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -74,6 +74,7 @@ public: void insertPositionedObject(RenderBox*); void removePositionedObject(RenderBox*); void removePositionedObjects(RenderBlock*); + ListHashSet<RenderBox*>* positionedObjects() const { return m_positionedObjects; } void addPercentHeightDescendant(RenderBox*); static void removePercentHeightDescendant(RenderBox*); @@ -89,8 +90,6 @@ public: bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); } bool containsFloat(RenderObject*); - IntRect floatRect() const; - int lineWidth(int y, bool firstLine) const; virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const; @@ -317,7 +316,6 @@ private: // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline // children. virtual RenderBlock* firstLineBlock() const; - bool inRootBlockContext() const; virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth); virtual RenderStyle* outlineStyleForRepaint() const; @@ -386,6 +384,7 @@ private: void calcColumnWidth(); int layoutColumns(int endOfContent = -1, int requestedColumnHeight = -1); + int visibleTopOfHighestFloatExtendingBelow(int bottom, int maxHeight) const; bool expandsToEncloseOverhangingFloats() const; diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index a7f3553..895db66 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -349,7 +349,8 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length; } HashSet<const SimpleFontData*> fallbackFonts; - r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, firstLine, &fallbackFonts)); + GlyphOverflow glyphOverflow; + r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, firstLine, &fallbackFonts, &glyphOverflow)); if (!fallbackFonts.isEmpty() #if ENABLE(SVG) && !isSVGText() @@ -358,6 +359,14 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool ASSERT(r->m_box->isText()); static_cast<InlineTextBox*>(r->m_box)->setFallbackFonts(fallbackFonts); } + if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right) +#if ENABLE(SVG) + && !isSVGText() +#endif + ) { + ASSERT(r->m_box->isText()); + static_cast<InlineTextBox*>(r->m_box)->setGlyphOverflow(glyphOverflow); + } } else if (!r->m_object->isRenderInline()) { RenderBox* renderBox = toRenderBox(r->m_object); renderBox->calcWidth(); @@ -753,7 +762,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i bool endLineMatched = false; bool checkForEndLineMatch = endLine; bool checkForFloatsFromLastLine = false; - int lastHeight = height(); bool isLineEmpty = true; @@ -842,6 +850,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i // Now position our text runs vertically. computeVerticalPositionsForLine(lineBox, resolver.firstRun()); + InlineTextBox::clearGlyphOverflowAndFallbackFontMap(); #if ENABLE(SVG) // Special SVG text layout code @@ -878,8 +887,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i } else m_floatingObjects->first(); for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { - if (f->m_bottom > lastHeight) - lastRootBox()->floats().append(f->m_renderer); + lastRootBox()->floats().append(f->m_renderer); ASSERT(f->m_renderer == floats[floatIndex].object); // If a float's geometry has changed, give up on syncing with clean lines. if (floats[floatIndex].rect != IntRect(f->m_left, f->m_top, f->m_width, f->m_bottom - f->m_top)) @@ -889,7 +897,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i lastFloat = m_floatingObjects->last(); } - lastHeight = height(); lineMidpointState.reset(); resolver.setPosition(end); } @@ -949,10 +956,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i m_floatingObjects->next(); } else m_floatingObjects->first(); - for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { - if (f->m_bottom > lastHeight) - lastRootBox()->floats().append(f->m_renderer); - } + for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) + lastRootBox()->floats().append(f->m_renderer); lastFloat = m_floatingObjects->last(); } size_t floatCount = floats.size(); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 66a88e2..bd82683 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -152,6 +152,16 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl removeFloatingOrPositionedChildFromBlockLists(); } } + if (FrameView *frameView = view()->frameView()) { + bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition; + bool oldStyleIsFixed = style() && style()->position() == FixedPosition; + if (newStyleIsFixed != oldStyleIsFixed) { + if (newStyleIsFixed) + frameView->addFixedObject(); + else + frameView->removeFixedObject(); + } + } RenderBoxModelObject::styleWillChange(diff, newStyle); } @@ -321,12 +331,17 @@ FloatQuad RenderBox::absoluteContentQuad() const return localToAbsoluteQuad(FloatRect(rect)); } -IntRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const +IntRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, IntPoint* cachedOffsetToRepaintContainer) const { IntRect box = borderBoundingBox(); adjustRectForOutlineAndShadow(box); - FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer); + FloatQuad containerRelativeQuad = FloatRect(box); + if (cachedOffsetToRepaintContainer) + containerRelativeQuad.move(cachedOffsetToRepaintContainer->x(), cachedOffsetToRepaintContainer->y()); + else + containerRelativeQuad = localToContainerQuad(containerRelativeQuad, repaintContainer); + box = containerRelativeQuad.enclosingBoundingBox(); // FIXME: layoutDelta needs to be applied in parts before/after transforms and @@ -429,7 +444,7 @@ bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, bool RenderBox::canBeScrolledAndHasScrollableArea() const { - return canBeProgramaticallyScrolled(false) && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth()); + return canBeProgramaticallyScrolled(false) && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth()); } bool RenderBox::canBeProgramaticallyScrolled(bool) const @@ -1175,10 +1190,9 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In IntPoint topLeft = rect.location(); topLeft.move(x(), y()); - if (style()->position() == FixedPosition) - fixed = true; + EPosition position = style()->position(); - if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) { + if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) { RenderBlock* cb = toRenderBlock(o); if (cb->hasColumns()) { IntRect repaintRect(topLeft, rect.size()); @@ -1191,16 +1205,17 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, In // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box // in the parent's coordinate space that encloses us. if (layer() && layer()->transform()) { - fixed = false; + fixed = position == FixedPosition; rect = layer()->transform()->mapRect(rect); // FIXME: this clobbers topLeft adjustment done for multicol above topLeft = rect.location(); topLeft.move(x(), y()); - } + } else if (position == FixedPosition) + fixed = true; - if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) + if (position == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) topLeft += toRenderInline(o)->relativePositionedInlineOffset(this); - else if (style()->position() == RelativePosition && layer()) { + else if (position == RelativePosition && layer()) { // Apply the relative position offset when invalidating a rectangle. The layer // is translated, but the render box isn't, so we need to do this to get the // right dirty rect. Since this is called from RenderObject::setStyle, the relative position diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 2ee368d..68bbd51 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -73,7 +73,7 @@ public: FloatQuad absoluteContentQuad() const; // Bounds of the outline box in absolute coords. Respects transforms - virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const; + virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/, IntPoint* cachedOffsetToRepaintContainer) const; virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); // Use this with caution! No type checking is done! @@ -271,9 +271,9 @@ public: virtual void paintMask(PaintInfo&, int tx, int ty); virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); - // Called when a positioned object moves but doesn't change size. A simplified layout is done - // that just updates the object's position. - virtual void tryLayoutDoingPositionedMovementOnly() + // Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted + // that just updates the object's position. If the size does change, the object remains dirty. + void tryLayoutDoingPositionedMovementOnly() { int oldWidth = width(); calcWidth(); diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index f8bf05e..9caf46f 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -131,7 +131,7 @@ bool RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(GraphicsCont data = gBoxModelObjects->get(object); const AffineTransform& currentTransform = context->getCTM(); - bool contextIsScaled = !currentTransform.isIdentityOrTranslation(); + bool contextIsScaled = !currentTransform.isIdentityOrTranslationOrFlipped(); if (!contextIsScaled && imageSize == size) { // There is no scale in effect. If we had a scale in effect before, we can just delete this data. if (data) { @@ -158,8 +158,10 @@ bool RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(GraphicsCont return false; } + const AffineTransform& tr = data->transform(); + bool scaleUnchanged = tr.a() == currentTransform.a() && tr.b() == currentTransform.b() && tr.c() == currentTransform.c() && tr.d() == currentTransform.d(); // We are scaled, but we painted already at this size, so just keep using whatever mode we last painted with. - if ((!contextIsScaled || data->transform() == currentTransform) && data->size() == size) + if ((!contextIsScaled || scaleUnchanged) && data->size() == size) return data->useLowQualityScale(); // We have data and our size just changed. If this change happened quickly, go into low quality mode and then set a repaint @@ -479,7 +481,9 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co context->clip(toRenderBox(this)->overflowClipRect(tx, ty)); // Now adjust our tx, ty, w, h to reflect a scrolled content box with borders at the ends. - layer()->subtractScrolledContentOffset(tx, ty); + IntSize offset = layer()->scrolledContentOffset(); + tx -= offset.width(); + ty -= offset.height(); w = bLeft + layer()->scrollWidth() + bRight; h = borderTop() + layer()->scrollHeight() + borderBottom(); } @@ -604,7 +608,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op; RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; Image* image = bg->image(clientForBackgroundImage, tileSize); - bool useLowQualityScaling = RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(context, this, image, destRect.size()); + bool useLowQualityScaling = RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(context, this, image, tileSize); context->drawTiledImage(image, style()->colorSpace(), destRect, phase, tileSize, compositeOp, useLowQualityScaling); } } @@ -632,6 +636,7 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, case SizeLength: { int w = positioningAreaSize.width(); int h = positioningAreaSize.height(); + Length layerWidth = fillLayer->size().size.width(); Length layerHeight = fillLayer->size().size.height(); @@ -647,15 +652,19 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, // If one of the values is auto we have to use the appropriate // scale to maintain our aspect ratio. - if (layerWidth.isAuto() && !layerHeight.isAuto()) - w = image->imageSize(this, style()->effectiveZoom()).width() * h / image->imageSize(this, style()->effectiveZoom()).height(); - else if (!layerWidth.isAuto() && layerHeight.isAuto()) - h = image->imageSize(this, style()->effectiveZoom()).height() * w / image->imageSize(this, style()->effectiveZoom()).width(); - else if (layerWidth.isAuto() && layerHeight.isAuto()) { - // If both width and height are auto, we just want to use the image's - // intrinsic size. - w = image->imageSize(this, style()->effectiveZoom()).width(); - h = image->imageSize(this, style()->effectiveZoom()).height(); + if (layerWidth.isAuto() && !layerHeight.isAuto()) { + IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); + if (imageIntrinsicSize.height()) + w = imageIntrinsicSize.width() * h / imageIntrinsicSize.height(); + } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { + IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); + if (imageIntrinsicSize.width()) + h = imageIntrinsicSize.height() * w / imageIntrinsicSize.width(); + } else if (layerWidth.isAuto() && layerHeight.isAuto()) { + // If both width and height are auto, use the image's intrinsic size. + IntSize imageIntrinsicSize = image->imageSize(this, style()->effectiveZoom()); + w = imageIntrinsicSize.width(); + h = imageIntrinsicSize.height(); } return IntSize(max(1, w), max(1, h)); @@ -663,15 +672,17 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, case Contain: case Cover: { IntSize imageIntrinsicSize = image->imageSize(this, 1); - float horizontalScaleFactor = static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width(); - float verticalScaleFactor = static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height(); + float horizontalScaleFactor = imageIntrinsicSize.width() + ? static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width() : 1; + float verticalScaleFactor = imageIntrinsicSize.height() + ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height() : 1; float scaleFactor = type == Contain ? min(horizontalScaleFactor, verticalScaleFactor) : max(horizontalScaleFactor, verticalScaleFactor); - return IntSize(max<int>(1, imageIntrinsicSize.width() * scaleFactor), max<int>(1, imageIntrinsicSize.height() * scaleFactor)); } case SizeNone: break; } + return image->imageSize(this, style()->effectiveZoom()); } @@ -791,7 +802,8 @@ int RenderBoxModelObject::verticalPosition(bool firstLine) const vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine) / 2 + baselinePosition(firstLine); else if (va == TEXT_BOTTOM) { vpos += f.descent(); - if (!isReplaced()) // lineHeight - baselinePosition is always 0 for replaced elements, so don't bother wasting time in that case. + // 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) - baselinePosition(firstLine)); } else if (va == BASELINE_MIDDLE) vpos += -lineHeight(firstLine) / 2 + baselinePosition(firstLine); @@ -822,10 +834,10 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, int imageWidth = imageSize.width(); int imageHeight = imageSize.height(); - int topSlice = min(imageHeight, ninePieceImage.m_slices.top().calcValue(imageHeight)); - int bottomSlice = min(imageHeight, ninePieceImage.m_slices.bottom().calcValue(imageHeight)); - int leftSlice = min(imageWidth, ninePieceImage.m_slices.left().calcValue(imageWidth)); - int rightSlice = min(imageWidth, ninePieceImage.m_slices.right().calcValue(imageWidth)); + int topSlice = min(imageHeight, ninePieceImage.slices().top().calcValue(imageHeight)); + int bottomSlice = min(imageHeight, ninePieceImage.slices().bottom().calcValue(imageHeight)); + int leftSlice = min(imageWidth, ninePieceImage.slices().left().calcValue(imageWidth)); + int rightSlice = min(imageWidth, ninePieceImage.slices().right().calcValue(imageWidth)); ENinePieceImageRule hRule = ninePieceImage.horizontalRule(); ENinePieceImageRule vRule = ninePieceImage.verticalRule(); @@ -915,15 +927,15 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, } void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, - const RenderStyle* style, bool begin, bool end) + const RenderStyle* style, bool begin, bool end) { if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage())) return; - const Color& topColor = style->borderTopColor(); - const Color& bottomColor = style->borderBottomColor(); - const Color& leftColor = style->borderLeftColor(); - const Color& rightColor = style->borderRightColor(); + const Color& topColor = style->visitedDependentColor(CSSPropertyBorderTopColor); + const Color& bottomColor = style->visitedDependentColor(CSSPropertyBorderBottomColor); + const Color& leftColor = style->visitedDependentColor(CSSPropertyBorderLeftColor); + const Color& rightColor = style->visitedDependentColor(CSSPropertyBorderRightColor); bool topTransparent = style->borderTopIsTransparent(); bool bottomTransparent = style->borderBottomIsTransparent(); @@ -988,7 +1000,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, x2 -= topRight.width(); } - drawLineForBoxSide(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, topColor, style->color(), topStyle, + drawLineForBoxSide(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, topColor, topStyle, ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth()); if (renderRadii) { @@ -1016,7 +1028,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw upper left arc drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, topLeft, firstAngleStart, firstAngleSpan, - BSTop, topColor, style->color(), topStyle, true); + BSTop, topColor, topStyle, true); if (applyLeftInnerClip) graphicsContext->restore(); } @@ -1042,7 +1054,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw upper right arc drawArcForBoxSide(graphicsContext, rightX, leftY, thickness, topRight, secondAngleStart, secondAngleSpan, - BSTop, topColor, style->color(), topStyle, false); + BSTop, topColor, topStyle, false); if (applyRightInnerClip) graphicsContext->restore(); } @@ -1065,7 +1077,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, x2 -= bottomRight.width(); } - drawLineForBoxSide(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bottomColor, style->color(), bottomStyle, + drawLineForBoxSide(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bottomColor, bottomStyle, ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth()); if (renderRadii) { @@ -1093,7 +1105,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw lower left arc drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, bottomLeft, firstAngleStart, firstAngleSpan, - BSBottom, bottomColor, style->color(), bottomStyle, true); + BSBottom, bottomColor, bottomStyle, true); if (applyLeftInnerClip) graphicsContext->restore(); } @@ -1115,7 +1127,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw lower right arc drawArcForBoxSide(graphicsContext, rightX, rightY, thickness, bottomRight, secondAngleStart, secondAngleSpan, - BSBottom, bottomColor, style->color(), bottomStyle, false); + BSBottom, bottomColor, bottomStyle, false); if (applyRightInnerClip) graphicsContext->restore(); } @@ -1138,7 +1150,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, y2 -= bottomLeft.height(); } - drawLineForBoxSide(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, leftColor, style->color(), leftStyle, + drawLineForBoxSide(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, leftColor, leftStyle, ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth()); if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) { @@ -1161,7 +1173,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw top left arc drawArcForBoxSide(graphicsContext, topX, topY, thickness, topLeft, firstAngleStart, firstAngleSpan, - BSLeft, leftColor, style->color(), leftStyle, true); + BSLeft, leftColor, leftStyle, true); if (applyTopInnerClip) graphicsContext->restore(); } @@ -1182,7 +1194,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw bottom left arc drawArcForBoxSide(graphicsContext, topX, bottomY, thickness, bottomLeft, secondAngleStart, secondAngleSpan, - BSLeft, leftColor, style->color(), leftStyle, false); + BSLeft, leftColor, leftStyle, false); if (applyBottomInnerClip) graphicsContext->restore(); } @@ -1207,7 +1219,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, y2 -= bottomRight.height(); } - drawLineForBoxSide(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rightColor, style->color(), rightStyle, + drawLineForBoxSide(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rightColor, rightStyle, ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth()); if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) { @@ -1230,7 +1242,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw top right arc drawArcForBoxSide(graphicsContext, topX, topY, thickness, topRight, firstAngleStart, firstAngleSpan, - BSRight, rightColor, style->color(), rightStyle, true); + BSRight, rightColor, rightStyle, true); if (applyTopInnerClip) graphicsContext->restore(); } @@ -1252,7 +1264,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, // Draw bottom right arc drawArcForBoxSide(graphicsContext, bottomX, bottomY, thickness, bottomRight, secondAngleStart, secondAngleSpan, - BSRight, rightColor, style->color(), rightStyle, false); + BSRight, rightColor, rightStyle, false); if (applyBottomInnerClip) graphicsContext->restore(); } @@ -1310,16 +1322,16 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int } bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255; - for (ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next) { - if (shadow->style != shadowStyle) + for (const ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next()) { + if (shadow->style() != shadowStyle) continue; - IntSize shadowOffset(shadow->x, shadow->y); - int shadowBlur = shadow->blur; - int shadowSpread = shadow->spread; - Color& shadowColor = shadow->color; + IntSize shadowOffset(shadow->x(), shadow->y()); + int shadowBlur = shadow->blur(); + int shadowSpread = shadow->spread(); + const Color& shadowColor = shadow->color(); - if (shadow->style == Normal) { + if (shadow->style() == Normal) { IntRect fillRect(rect); fillRect.inflate(shadowSpread); if (fillRect.isEmpty()) diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index db32808..8619fc0 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -24,18 +24,26 @@ #include "config.h" #include "RenderEmbeddedObject.h" +#include "CSSValueKeywords.h" +#include "Font.h" +#include "FontSelector.h" #include "Frame.h" #include "FrameLoaderClient.h" +#include "GraphicsContext.h" #include "HTMLEmbedElement.h" #include "HTMLIFrameElement.h" #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "HTMLParamElement.h" +#include "LocalizedStrings.h" #include "MIMETypeRegistry.h" #include "Page.h" +#include "Path.h" #include "PluginWidget.h" +#include "RenderTheme.h" #include "RenderView.h" #include "RenderWidgetProtector.h" +#include "Settings.h" #include "Text.h" #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) @@ -49,9 +57,16 @@ namespace WebCore { using namespace HTMLNames; + +static const float replacementTextRoundedRectHeight = 18; +static const float replacementTextRoundedRectLeftRightTextMargin = 6; +static const float replacementTextRoundedRectOpacity = 0.20f; +static const float replacementTextRoundedRectRadius = 5; +static const float replacementTextTextOpacity = 0.55f; RenderEmbeddedObject::RenderEmbeddedObject(Element* element) - : RenderPartObject(element) + : RenderPart(element) + , m_hasFallbackContent(false) { view()->frameView()->setIsVisuallyNonEmpty(); } @@ -65,7 +80,7 @@ RenderEmbeddedObject::~RenderEmbeddedObject() #if USE(ACCELERATED_COMPOSITING) bool RenderEmbeddedObject::requiresLayer() const { - if (RenderPartObject::requiresLayer()) + if (RenderPart::requiresLayer()) return true; return allowsAcceleratedCompositing(); @@ -141,6 +156,9 @@ static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramV void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) { + if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called. + return; + String url; String serviceType; Vector<String> paramNames; @@ -306,29 +324,86 @@ void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins) #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) { HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node()); + KURL kurl; + mediaElement->getPluginProxyParams(kurl, paramNames, paramValues); mediaElement->setNeedWidgetUpdate(false); - if (node()->hasTagName(videoTag)) { - HTMLVideoElement* vid = static_cast<HTMLVideoElement*>(node()); - String poster = vid->poster(); - if (!poster.isEmpty()) { - paramNames.append("_media_element_poster_"); - paramValues.append(poster); - } - } + frame->loader()->loadMediaPlayerProxyPlugin(node(), kurl, paramNames, paramValues); + } +#endif +} - url = mediaElement->initialURL(); - if (!url.isEmpty()) { - paramNames.append("_media_element_src_"); - paramValues.append(url); - } +void RenderEmbeddedObject::setShowsMissingPluginIndicator() +{ + m_replacementText = missingPluginText(); +} - serviceType = "application/x-media-element-proxy-plugin"; - - if (mediaElement->dispatchBeforeLoadEvent(url)) - frame->loader()->requestObject(this, url, nullAtom, serviceType, paramNames, paramValues); +void RenderEmbeddedObject::setShowsCrashedPluginIndicator() +{ + m_replacementText = crashedPluginText(); +} + +void RenderEmbeddedObject::paint(PaintInfo& paintInfo, int tx, int ty) +{ + if (!m_replacementText.isNull()) { + RenderReplaced::paint(paintInfo, tx, ty); + return; } -#endif + + RenderPart::paint(paintInfo, tx, ty); +} + +void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, int tx, int ty) +{ + if (!m_replacementText) + return; + + if (paintInfo.phase == PaintPhaseSelection) + return; + + GraphicsContext* context = paintInfo.context; + if (context->paintingDisabled()) + return; + + FloatRect pluginRect = contentBoxRect(); + pluginRect.move(tx, ty); + + FontDescription fontDescription; + RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription); + fontDescription.setWeight(FontWeightBold); + Settings* settings = document()->settings(); + ASSERT(settings); + if (!settings) + return; + fontDescription.setRenderingMode(settings->fontRenderingMode()); + fontDescription.setComputedSize(fontDescription.specifiedSize()); + Font font(fontDescription, 0, 0); + font.update(0); + + TextRun run(m_replacementText.characters(), m_replacementText.length()); + run.disableRoundingHacks(); + float textWidth = font.floatWidth(run); + + FloatRect replacementTextRect; + replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight)); + replacementTextRect.setLocation(FloatPoint((pluginRect.size().width() / 2 - replacementTextRect.size().width() / 2) + pluginRect.location().x(), + (pluginRect.size().height() / 2 - replacementTextRect.size().height() / 2) + pluginRect.location().y())); + + Path path = Path::createRoundedRectangle(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius)); + context->save(); + context->clip(pluginRect); + context->beginPath(); + context->addPath(path); + context->setAlpha(replacementTextRoundedRectOpacity); + context->setFillColor(Color::white, style()->colorSpace()); + context->fillPath(); + + FloatPoint labelPoint(roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2), + roundf(replacementTextRect.location().y()+ (replacementTextRect.size().height() - font.height()) / 2 + font.ascent())); + context->setAlpha(replacementTextTextOpacity); + context->setFillColor(Color::black, style()->colorSpace()); + context->drawBidiText(font, run, labelPoint); + context->restore(); } void RenderEmbeddedObject::layout() @@ -349,4 +424,23 @@ void RenderEmbeddedObject::layout() setNeedsLayout(false); } +void RenderEmbeddedObject::viewCleared() +{ + // This is required for <object> elements whose contents are rendered by WebCore (e.g. src="foo.html"). + if (node() && widget() && widget()->isFrameView()) { + FrameView* view = static_cast<FrameView*>(widget()); + int marginw = -1; + int marginh = -1; + if (node()->hasTagName(iframeTag)) { + HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node()); + marginw = frame->getMarginWidth(); + marginh = frame->getMarginHeight(); + } + if (marginw != -1) + view->setMarginWidth(marginw); + if (marginh != -1) + view->setMarginHeight(marginh); + } +} + } diff --git a/WebCore/rendering/RenderEmbeddedObject.h b/WebCore/rendering/RenderEmbeddedObject.h index bdaea92..b68108d 100644 --- a/WebCore/rendering/RenderEmbeddedObject.h +++ b/WebCore/rendering/RenderEmbeddedObject.h @@ -23,17 +23,22 @@ #ifndef RenderEmbeddedObject_h #define RenderEmbeddedObject_h -#include "RenderPartObject.h" +#include "RenderPart.h" namespace WebCore { -// Renderer for embeds and objects. -class RenderEmbeddedObject : public RenderPartObject { +// Renderer for embeds and objects, often, but not always, rendered via plug-ins. +// For example, <embed src="foo.html"> does not invoke a plug-in. +class RenderEmbeddedObject : public RenderPart { public: RenderEmbeddedObject(Element*); virtual ~RenderEmbeddedObject(); void updateWidget(bool onlyCreateNonNetscapePlugins); + void setShowsMissingPluginIndicator(); + void setShowsCrashedPluginIndicator(); + + bool hasFallbackContent() const { return m_hasFallbackContent; } #if USE(ACCELERATED_COMPOSITING) virtual bool allowsAcceleratedCompositing() const; @@ -43,11 +48,18 @@ private: virtual const char* renderName() const { return "RenderEmbeddedObject"; } virtual bool isEmbeddedObject() const { return true; } + virtual void paintReplaced(PaintInfo&, int, int); + virtual void paint(PaintInfo& paintInfo, int, int); + #if USE(ACCELERATED_COMPOSITING) virtual bool requiresLayer() const; #endif virtual void layout(); + virtual void viewCleared(); + + String m_replacementText; + bool m_hasFallbackContent; }; inline RenderEmbeddedObject* toRenderEmbeddedObject(RenderObject* object) diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index 889b0bc..d8cbd00 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "RenderFieldset.h" +#include "CSSPropertyNames.h" #include "HTMLNames.h" #include "GraphicsContext.h" @@ -181,8 +182,8 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty) void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style, int lx, int lw, int lb) { - const Color& tc = style->borderTopColor(); - const Color& bc = style->borderBottomColor(); + const Color& tc = style->visitedDependentColor(CSSPropertyBorderTopColor); + const Color& bc = style->visitedDependentColor(CSSPropertyBorderBottomColor); EBorderStyle ts = style->borderTopStyle(); EBorderStyle bs = style->borderBottomStyle(); @@ -199,22 +200,22 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in if (render_t) { if (lx >= borderLeftWidth) - drawLineForBoxSide(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, style->color(), ts, + drawLineForBoxSide(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, ts, (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0), (lx >= w && render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0)); if (lx + lw <= w - borderRightWidth) - drawLineForBoxSide(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts, + drawLineForBoxSide(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, ts, (lx + lw <= 0 && render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0), (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0)); } if (render_b) - drawLineForBoxSide(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, style->color(), bs, + drawLineForBoxSide(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, bs, (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0), (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0)); if (render_l) { - const Color& lc = style->borderLeftColor(); + const Color& lc = style->visitedDependentColor(CSSPropertyBorderLeftColor); int startY = ty; bool ignore_top = @@ -233,12 +234,12 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in startY = lb; } - drawLineForBoxSide(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, style->color(), ls, - ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth()); + drawLineForBoxSide(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, ls, + ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth()); } if (render_r) { - const Color& rc = style->borderRightColor(); + const Color& rc = style->visitedDependentColor(CSSPropertyBorderRightColor); int startY = ty; bool ignore_top = @@ -257,7 +258,7 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in startY = lb; } - drawLineForBoxSide(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, style->color(), rs, + drawLineForBoxSide(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, rs, ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth()); } } diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index a31442a..6a5c1e0 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -114,10 +114,10 @@ String RenderFileUploadControl::acceptTypes() return static_cast<HTMLInputElement*>(node())->accept(); } -void RenderFileUploadControl::iconForFiles(const Vector<String>& filenames) +void RenderFileUploadControl::chooseIconForFiles(FileChooser* chooser, const Vector<String>& filenames) { if (Chrome* chromePointer = chrome()) - chromePointer->iconForFiles(filenames, m_fileChooser); + chromePointer->chooseIconForFiles(filenames, chooser); } void RenderFileUploadControl::click() @@ -195,6 +195,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty) { if (style()->visibility() != VISIBLE) return; + ASSERT(m_fileChooser); // Push a clip. if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h index 454041a..1427dbf 100644 --- a/WebCore/rendering/RenderFileUploadControl.h +++ b/WebCore/rendering/RenderFileUploadControl.h @@ -61,7 +61,7 @@ private: void repaint() { RenderBlock::repaint(); } bool allowsMultipleFiles(); String acceptTypes(); - void iconForFiles(const Vector<String>&); + void chooseIconForFiles(FileChooser*, const Vector<String>&); Chrome* chrome() const; int maxFilenameWidth() const; diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp index aa28ff0..9f0889b 100644 --- a/WebCore/rendering/RenderForeignObject.cpp +++ b/WebCore/rendering/RenderForeignObject.cpp @@ -36,6 +36,7 @@ namespace WebCore { RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node) : RenderSVGBlock(node) + , m_needsTransformUpdate(true) { } @@ -99,9 +100,12 @@ void RenderForeignObject::layout() ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree. LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); - m_localTransform = foreign->animatedLocalTransform(); + + if (m_needsTransformUpdate) { + m_localTransform = foreign->animatedLocalTransform(); + m_needsTransformUpdate = false; + } // Cache viewport boundaries FloatPoint viewportLocation(foreign->x().value(foreign), foreign->y().value(foreign)); diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h index bb6b555..d8c1f68 100644 --- a/WebCore/rendering/RenderForeignObject.h +++ b/WebCore/rendering/RenderForeignObject.h @@ -54,6 +54,7 @@ public: virtual bool isSVGForeignObject() const { return true; } virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const; + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: virtual void calcWidth(); @@ -62,6 +63,7 @@ public: virtual const AffineTransform& localToParentTransform() const; virtual AffineTransform localTransform() const { return m_localTransform; } + bool m_needsTransformUpdate : 1; FloatRect m_viewport; AffineTransform m_localTransform; mutable AffineTransform m_localToParentTransform; diff --git a/WebCore/rendering/RenderFrame.cpp b/WebCore/rendering/RenderFrame.cpp index ffe87c2..3932c9a 100644 --- a/WebCore/rendering/RenderFrame.cpp +++ b/WebCore/rendering/RenderFrame.cpp @@ -37,7 +37,7 @@ namespace WebCore { RenderFrame::RenderFrame(HTMLFrameElement* frame) - : RenderPart(frame) + : RenderFrameBase(frame) { setInline(false); } @@ -65,6 +65,7 @@ void RenderFrame::viewCleared() view->setMarginHeight(marginh); } +<<<<<<< HEAD #ifdef FLATTEN_FRAMESET void RenderFrame::layout() { @@ -145,4 +146,6 @@ void RenderFrame::layoutWithFlattening(bool fixedWidth, bool fixedHeight) setNeedsLayout(false); } +======= +>>>>>>> webkit.org at r58033 } // namespace WebCore diff --git a/WebCore/rendering/RenderFrame.h b/WebCore/rendering/RenderFrame.h index a66aa14..8f87b79 100644 --- a/WebCore/rendering/RenderFrame.h +++ b/WebCore/rendering/RenderFrame.h @@ -23,19 +23,18 @@ #ifndef RenderFrame_h #define RenderFrame_h -#include "RenderPart.h" +#include "RenderFrameBase.h" #include "RenderFrameSet.h" namespace WebCore { class HTMLFrameElement; -class RenderFrame : public RenderPart { +class RenderFrame : public RenderFrameBase { public: RenderFrame(HTMLFrameElement*); FrameEdgeInfo edgeInfo() const; - void layoutWithFlattening(bool fixedWidth, bool fixedHeight); private: virtual const char* renderName() const { return "RenderFrame"; } diff --git a/WebCore/rendering/RenderFrameBase.cpp b/WebCore/rendering/RenderFrameBase.cpp new file mode 100644 index 0000000..4a62f8a --- /dev/null +++ b/WebCore/rendering/RenderFrameBase.cpp @@ -0,0 +1,93 @@ +/* + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#include "config.h" +#include "RenderFrameBase.h" + +#include "FrameView.h" +#include "HTMLFrameElementBase.h" +#include "RenderView.h" + +namespace WebCore { + +RenderFrameBase::RenderFrameBase(Element* element) + : RenderPart(element) +{ +} + +void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight) +{ + FrameView* childFrameView = static_cast<FrameView*>(widget()); + RenderView* childRoot = childFrameView ? static_cast<RenderView*>(childFrameView->frame()->contentRenderer()) : 0; + + // Do not expand frames which has zero width or height + if (!width() || !height() || !childRoot) { + updateWidgetPosition(); + if (childFrameView) + childFrameView->layout(); + setNeedsLayout(false); + return; + } + + // need to update to calculate min/max correctly + updateWidgetPosition(); + if (childRoot->prefWidthsDirty()) + childRoot->calcPrefWidths(); + + // if scrollbars are off, and the width or height are fixed + // we obey them and do not expand. With frame flattening + // no subframe much ever become scrollable. + + HTMLFrameElementBase* element = static_cast<HTMLFrameElementBase*>(node()); + bool isScrollable = element->scrollingMode() != ScrollbarAlwaysOff; + + // consider iframe inset border + int hBorder = borderLeft() + borderRight(); + int vBorder = borderTop() + borderBottom(); + + // make sure minimum preferred width is enforced + if (isScrollable || !fixedWidth) { + setWidth(max(width(), childRoot->minPrefWidth() + hBorder)); + // update again to pass the new width to the child frame + updateWidgetPosition(); + childFrameView->layout(); + } + + // expand the frame by setting frame height = content height + if (isScrollable || !fixedHeight || childRoot->isFrameSet()) + setHeight(max(height(), childFrameView->contentsHeight() + vBorder)); + if (isScrollable || !fixedWidth || childRoot->isFrameSet()) + setWidth(max(width(), childFrameView->contentsWidth() + hBorder)); + + updateWidgetPosition(); + + ASSERT(!childFrameView->layoutPending()); + ASSERT(!childRoot->needsLayout()); + ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChild() || !childRoot->firstChild()->firstChild()->needsLayout()); + + setNeedsLayout(false); +} + +} diff --git a/WebCore/rendering/RenderFrameBase.h b/WebCore/rendering/RenderFrameBase.h new file mode 100644 index 0000000..cd3cf0c --- /dev/null +++ b/WebCore/rendering/RenderFrameBase.h @@ -0,0 +1,44 @@ +/* + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 RenderFrameBase_h +#define RenderFrameBase_h + +#include "RenderPart.h" + +namespace WebCore { + +// Base class for RenderFrame and RenderIFrame +class RenderFrameBase : public RenderPart { +protected: + RenderFrameBase(Element*); + +public: + void layoutWithFlattening(bool fixedWidth, bool fixedHeight); +}; + +} // namespace WebCore + +#endif // RenderFrameBase_h diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp index cf78b2b..fca304c 100644 --- a/WebCore/rendering/RenderFrameSet.cpp +++ b/WebCore/rendering/RenderFrameSet.cpp @@ -749,7 +749,7 @@ void RenderFrameSet::positionFramesWithFlattening() bool RenderFrameSet::flattenFrameSet() const { - return document()->frame() && document()->frame()->settings()->frameSetFlatteningEnabled(); + return document()->frame() && document()->frame()->settings()->frameFlatteningEnabled(); } void RenderFrameSet::startResizing(GridAxis& axis, int position) diff --git a/WebCore/rendering/RenderFrameSet.h b/WebCore/rendering/RenderFrameSet.h index a4c8963..1e192fb 100644 --- a/WebCore/rendering/RenderFrameSet.h +++ b/WebCore/rendering/RenderFrameSet.h @@ -70,11 +70,14 @@ public: bool canResizeRow(const IntPoint&) const; bool canResizeColumn(const IntPoint&) const; +<<<<<<< HEAD #ifdef FLATTEN_FRAMESET void setGridNeedsLayout() { m_gridCalculated = false; } #endif bool flattenFrameSet() const; +======= +>>>>>>> webkit.org at r58033 private: static const int noSplit = -1; @@ -100,9 +103,11 @@ private: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); virtual void paint(PaintInfo&, int tx, int ty); virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; - + inline HTMLFrameSetElement* frameSet() const; + bool flattenFrameSet() const; + void setIsResizing(bool); void layOutAxis(GridAxis&, const Length*, int availableSpace); diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp new file mode 100644 index 0000000..bfea7bd --- /dev/null +++ b/WebCore/rendering/RenderIFrame.cpp @@ -0,0 +1,146 @@ +/* + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#include "config.h" +#include "RenderIFrame.h" + +#include "FrameView.h" +#include "HTMLIFrameElement.h" +#include "RenderView.h" +#include "Settings.h" + +namespace WebCore { + +using namespace HTMLNames; + +RenderIFrame::RenderIFrame(Element* element) + : RenderFrameBase(element) +{ +} + +void RenderIFrame::calcHeight() +{ + RenderPart::calcHeight(); + if (!flattenFrame()) + return; + + HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node()); + bool isScrollable = frame->scrollingMode() != ScrollbarAlwaysOff; + + if (isScrollable || !style()->height().isFixed()) { + FrameView* view = static_cast<FrameView*>(widget()); + int border = borderTop() + borderBottom(); + setHeight(max(height(), view->contentsHeight() + border)); + } +} + +void RenderIFrame::calcWidth() +{ + RenderPart::calcWidth(); + if (!flattenFrame()) + return; + + HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node()); + bool isScrollable = frame->scrollingMode() != ScrollbarAlwaysOff; + + if (isScrollable || !style()->width().isFixed()) { + FrameView* view = static_cast<FrameView*>(widget()); + int border = borderLeft() + borderRight(); + setWidth(max(width(), view->contentsWidth() + border)); + } +} + +bool RenderIFrame::flattenFrame() +{ + if (!node() || !node()->hasTagName(iframeTag)) + return false; + + HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node()); + bool isScrollable = element->scrollingMode() != ScrollbarAlwaysOff; + + if (!isScrollable && style()->width().isFixed() + && style()->height().isFixed()) + return false; + + Frame* frame = element->document()->frame(); + bool enabled = frame && frame->settings()->frameFlatteningEnabled(); + + if (!enabled || !frame->page()) + return false; + + FrameView* view = frame->page()->mainFrame()->view(); + if (!view) + return false; + + // Do not flatten offscreen inner frames during frame flattening. + return absoluteBoundingBoxRect().intersects(IntRect(IntPoint(0, 0), view->contentsSize())); +} + +void RenderIFrame::layout() +{ + ASSERT(needsLayout()); + + RenderPart::calcWidth(); + RenderPart::calcHeight(); + + if (flattenFrame()) { + layoutWithFlattening(style()->width().isFixed(), style()->height().isFixed()); + return; + } + + RenderPart::layout(); + + m_overflow.clear(); + addShadowOverflow(); + + setNeedsLayout(false); +} + +#if USE(ACCELERATED_COMPOSITING) +bool RenderIFrame::requiresLayer() const +{ + if (RenderPart::requiresLayer()) + return true; + + return requiresAcceleratedCompositing(); +} + +bool RenderIFrame::requiresAcceleratedCompositing() const +{ + if (!node() || !node()->hasTagName(iframeTag)) + return false; + + // If the contents of the iframe are composited, then we have to be as well. + HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node()); + if (Document* contentDocument = element->contentDocument()) { + if (RenderView* view = contentDocument->renderView()) + return view->usesCompositing(); + } + + return false; +} +#endif + +} diff --git a/WebCore/rendering/RenderIFrame.h b/WebCore/rendering/RenderIFrame.h new file mode 100644 index 0000000..ab659a4 --- /dev/null +++ b/WebCore/rendering/RenderIFrame.h @@ -0,0 +1,76 @@ +/* + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 RenderIFrame_h +#define RenderIFrame_h + +#include "RenderFrameBase.h" + +namespace WebCore { + +class RenderIFrame : public RenderFrameBase { +public: + RenderIFrame(Element*); + +#if USE(ACCELERATED_COMPOSITING) + bool requiresAcceleratedCompositing() const; +#endif + +private: + virtual void calcHeight(); + virtual void calcWidth(); + + virtual void layout(); + +#if USE(ACCELERATED_COMPOSITING) + virtual bool requiresLayer() const; +#endif + virtual bool isRenderIFrame() const { return true; } + + virtual const char* renderName() const { return "RenderPartObject"; } // Lying for now to avoid breaking tests + + bool flattenFrame(); + +}; + +inline RenderIFrame* toRenderIFrame(RenderObject* object) +{ + ASSERT(!object || object->isRenderIFrame()); + return static_cast<RenderIFrame*>(object); +} + +inline const RenderIFrame* toRenderIFrame(const RenderObject* object) +{ + ASSERT(!object || object->isRenderIFrame()); + return static_cast<const RenderIFrame*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderIFrame(const RenderIFrame*); + + +} // namespace WebCore + +#endif // RenderIFrame_h diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 881d0b4..a2052fe 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -480,7 +480,7 @@ void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style Vector<Path> focusRingPaths; focusRingPaths.append(areaElement->getPath(this)); - paintInfo.context->drawFocusRing(focusRingPaths, style->outlineWidth(), style->outlineOffset(), style->outlineColor()); + paintInfo.context->drawFocusRing(focusRingPaths, style->outlineWidth(), style->outlineOffset(), style->visitedDependentColor(CSSPropertyOutlineColor)); break; } } diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index d254835..6d3f462 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -80,7 +80,7 @@ void RenderInline::destroy() // not have a parent that means they are either already disconnected or // root lines that can just be destroyed without disconnecting. if (firstLineBox()->parent()) { - for (InlineRunBox* box = firstLineBox(); box; box = box->nextLineBox()) + for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) box->remove(); } } else if (isInline() && parent()) @@ -410,7 +410,7 @@ void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty) void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty) { - if (InlineRunBox* curr = firstLineBox()) { + if (InlineFlowBox* curr = firstLineBox()) { for (; curr; curr = curr->nextLineBox()) rects.append(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())); } else @@ -429,7 +429,7 @@ void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty) void RenderInline::absoluteQuads(Vector<FloatQuad>& quads) { - if (InlineRunBox* curr = firstLineBox()) { + if (InlineFlowBox* curr = firstLineBox()) { for (; curr; curr = curr->nextLineBox()) { FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height()); quads.append(localToAbsoluteQuad(localRect)); @@ -534,7 +534,7 @@ IntRect RenderInline::linesBoundingBox() const // Return the width of the minimal left side and the maximal right side. int leftSide = 0; int rightSide = 0; - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (curr == firstLineBox() || curr->x() < leftSide) leftSide = curr->x(); if (curr == firstLineBox() || curr->x() + curr->width() > rightSide) @@ -557,7 +557,7 @@ IntRect RenderInline::linesVisibleOverflowBoundingBox() const // Return the width of the minimal left side and the maximal right side. int leftSide = numeric_limits<int>::max(); int rightSide = numeric_limits<int>::min(); - for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { leftSide = min(leftSide, curr->leftVisibleOverflow()); rightSide = max(rightSide, curr->rightVisibleOverflow()); } @@ -599,11 +599,10 @@ IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repain // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. - int x = r.x(); - int y = r.y(); + IntRect repaintRect(r); + repaintRect.move(-cb->layer()->scrolledContentOffset()); // For overflow:auto/scroll/hidden. + IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height()); - cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden. - IntRect repaintRect(x, y, r.width(), r.height()); r = intersection(repaintRect, boxRect); } @@ -928,7 +927,7 @@ void RenderInline::imageChanged(WrappedImagePtr, const IntRect*) void RenderInline::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty) { - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { RootInlineBox* root = curr->root(); int top = max(root->lineTop(), curr->y()); int bottom = min(root->lineBottom(), curr->y() + curr->height()); @@ -966,27 +965,26 @@ void RenderInline::paintOutline(GraphicsContext* graphicsContext, int tx, int ty if (!hasOutline()) return; - if (style()->outlineStyleIsAuto() || hasOutlineAnnotation()) { - int ow = style()->outlineWidth(); - Color oc = style()->outlineColor(); - if (!oc.isValid()) - oc = style()->color(); + RenderStyle* styleToUse = style(); + if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) { + int ow = styleToUse->outlineWidth(); + Color oc = styleToUse->visitedDependentColor(CSSPropertyOutlineColor); Vector<IntRect> focusRingRects; addFocusRingRects(focusRingRects, tx, ty); - if (style()->outlineStyleIsAuto()) - graphicsContext->drawFocusRing(focusRingRects, ow, style()->outlineOffset(), oc); + if (styleToUse->outlineStyleIsAuto()) + graphicsContext->drawFocusRing(focusRingRects, ow, styleToUse->outlineOffset(), oc); else addPDFURLRect(graphicsContext, unionRect(focusRingRects)); } - if (style()->outlineStyleIsAuto() || style()->outlineStyle() == BNONE) + if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE) return; Vector<IntRect> rects; rects.append(IntRect()); - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { RootInlineBox* root = curr->root(); int top = max(root->lineTop(), curr->y()); int bottom = min(root->lineBottom(), curr->y() + curr->height()); @@ -1001,11 +999,10 @@ void RenderInline::paintOutline(GraphicsContext* graphicsContext, int tx, int ty void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& lastline, const IntRect& thisline, const IntRect& nextline) { - int ow = style()->outlineWidth(); - EBorderStyle os = style()->outlineStyle(); - Color oc = style()->outlineColor(); - if (!oc.isValid()) - oc = style()->color(); + RenderStyle* styleToUse = style(); + int ow = styleToUse->outlineWidth(); + EBorderStyle os = styleToUse->outlineStyle(); + Color oc = styleToUse->visitedDependentColor(CSSPropertyOutlineColor); int offset = style()->outlineOffset(); @@ -1021,7 +1018,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, l, b + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : 0), BSLeft, - oc, style()->color(), os, + oc, os, (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : -ow), (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : -ow)); @@ -1032,7 +1029,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, r + ow, b + (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : 0), BSRight, - oc, style()->color(), os, + oc, os, (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : -ow), (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : -ow)); // upper edge @@ -1042,7 +1039,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, t - ow, min(r+ow, (lastline.isEmpty() ? 1000000 : tx + lastline.x())), t , - BSTop, oc, style()->color(), os, + BSTop, oc, os, ow, (!lastline.isEmpty() && tx + lastline.x() + 1 < r + ow) ? -ow : ow); @@ -1052,7 +1049,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, t - ow, r + ow, t , - BSTop, oc, style()->color(), os, + BSTop, oc, os, (!lastline.isEmpty() && l - ow < tx + lastline.right()) ? -ow : ow, ow); @@ -1063,7 +1060,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, b, min(r + ow, !nextline.isEmpty() ? tx + nextline.x() + 1 : 1000000), b + ow, - BSBottom, oc, style()->color(), os, + BSBottom, oc, os, ow, (!nextline.isEmpty() && tx + nextline.x() + 1 < r + ow) ? -ow : ow); @@ -1073,7 +1070,7 @@ void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, b, r + ow, b + ow, - BSBottom, oc, style()->color(), os, + BSBottom, oc, os, (!nextline.isEmpty() && l - ow < tx + nextline.right()) ? -ow : ow, ow); } diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 03a1e75..7994325 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * Portions are Copyright (C) 1998 Netscape Communications Corporation. * @@ -44,7 +44,6 @@ #include "config.h" #include "RenderLayer.h" -#include "CString.h" #include "CSSPropertyNames.h" #include "CSSStyleDeclaration.h" #include "CSSStyleSelector.h" @@ -83,6 +82,7 @@ #include "TransformationMatrix.h" #include "TransformState.h" #include "TranslateTransformOperation.h" +#include <wtf/text/CString.h> #include <wtf/StdLibExtras.h> #include <wtf/UnusedParam.h> @@ -245,7 +245,7 @@ bool RenderLayer::hasAcceleratedCompositing() const #endif } -void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) +void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset) { if (flags & DoFullRepaint) { renderer()->repaint(); @@ -259,13 +259,49 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) #endif } + updateLayerPosition(); // For relpositioned layers or non-positioned layers, // we need to keep in sync, since we may have shifted relative // to our parent layer. + IntPoint oldCachedOffset; + if (cachedOffset) { + // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation + bool disableOffsetCache = renderer()->hasColumns() || renderer()->hasTransform() || isComposited(); +#if ENABLE(SVG) + disableOffsetCache = disableOffsetCache || renderer()->isSVGRoot(); +#endif + if (disableOffsetCache) + cachedOffset = 0; // If our cached offset is invalid make sure it's not passed to any of our children + else { + oldCachedOffset = *cachedOffset; + // Frequently our parent layer's renderer will be the same as our renderer's containing block. In that case, + // we just update the cache using our offset to our parent (which is m_x / m_y). Otherwise, regenerated cached + // offsets to the root from the render tree. + if (!m_parent || m_parent->renderer() == renderer()->containingBlock()) + cachedOffset->move(m_x, m_y); // Fast case + else { + int x = 0; + int y = 0; + convertToLayerCoords(root(), x, y); + *cachedOffset = IntPoint(x, y); + } + } + } int x = 0; int y = 0; - convertToLayerCoords(root(), x, y); + if (cachedOffset) { + x += cachedOffset->x(); + y += cachedOffset->y(); +#ifndef NDEBUG + int nonCachedX = 0; + int nonCachedY = 0; + convertToLayerCoords(root(), nonCachedX, nonCachedY); + ASSERT(x == nonCachedX); + ASSERT(y == nonCachedY); +#endif + } else + convertToLayerCoords(root(), x, y); positionOverflowControls(x, y); updateVisibilityStatus(); @@ -281,7 +317,9 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer); - IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer); + IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, cachedOffset); + // FIXME: Should ASSERT that value calculated for newOutlineBox using the cached offset is the same + // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048 if (flags & CheckForRepaint) { if (view && !view->printing()) { if (m_needsFullRepaint) { @@ -289,7 +327,7 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) if (newRect != m_repaintRect) renderer()->repaintUsingContainer(repaintContainer, newRect); } else - renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox); + renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox, &newRect, &newOutlineBox); } } m_repaintRect = newRect; @@ -313,7 +351,7 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) #endif for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) - child->updateLayerPositions(flags); + child->updateLayerPositions(flags, cachedOffset); #if USE(ACCELERATED_COMPOSITING) if ((flags & UpdateCompositingLayers) && isComposited()) @@ -323,6 +361,9 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) // With all our children positioned, now update our marquee if we need to. if (m_marquee) m_marquee->updateMarqueePosition(); + + if (cachedOffset) + *cachedOffset = oldCachedOffset; } void RenderLayer::computeRepaintRects() @@ -332,6 +373,22 @@ void RenderLayer::computeRepaintRects() m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer); } +void RenderLayer::updateRepaintRectsAfterScroll(bool fixed) +{ + if (fixed || renderer()->style()->position() == FixedPosition) { + computeRepaintRects(); + fixed = true; + } else if (renderer()->hasTransform()) { + // Transforms act as fixed position containers, so nothing inside a + // transformed element can be fixed relative to the viewport if the + // transformed element is not fixed itself or child of a fixed element. + return; + } + + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->updateRepaintRectsAfterScroll(fixed); +} + void RenderLayer::updateTransform() { // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set, @@ -571,15 +628,20 @@ void RenderLayer::updateLayerPosition() RenderLayer* positionedParent = enclosingPositionedAncestor(); // For positioned layers, we subtract out the enclosing positioned layer's scroll offset. - positionedParent->subtractScrolledContentOffset(x, y); + IntSize offset = positionedParent->scrolledContentOffset(); + x -= offset.width(); + y -= offset.height(); if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) { IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer())); x += offset.width(); y += offset.height(); } - } else if (parent()) - parent()->subtractScrolledContentOffset(x, y); + } else if (parent()) { + IntSize offset = parent()->scrolledContentOffset(); + x -= offset.width(); + y -= offset.height(); + } // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers. @@ -714,6 +776,11 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const RenderLayer* RenderLayer::clippingRoot() const { +#if USE(ACCELERATED_COMPOSITING) + if (isComposited()) + return const_cast<RenderLayer*>(this); +#endif + const RenderLayer* current = this; while (current) { if (current->renderer()->isRenderView()) @@ -1175,21 +1242,6 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) } } - -void -RenderLayer::addScrolledContentOffset(int& x, int& y) const -{ - x += scrollXOffset() + m_scrollLeftOverflow; - y += scrollYOffset(); -} - -void -RenderLayer::subtractScrolledContentOffset(int& x, int& y) const -{ - x -= scrollXOffset() + m_scrollLeftOverflow; - y -= scrollYOffset(); -} - void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint) { RenderBox* box = renderBox(); @@ -1250,15 +1302,24 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai view->updateWidgetPositions(); } - // The caret rect needs to be invalidated after scrolling + RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); + IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer); + Frame* frame = renderer()->document()->frame(); - if (frame) + if (frame) { + // The caret rect needs to be invalidated after scrolling frame->selection()->setNeedsLayout(); + FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint); + if (repaintContainer) + quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent); + frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent); + } + // Just schedule a full repaint of our object. - if (repaint) - renderer()->repaint(); - + if (view && repaint) + renderer()->repaintUsingContainer(repaintContainer, rectForRepaint); + if (updateScrollbars) { if (m_hBar) m_hBar->setValue(scrollXOffset()); @@ -2876,17 +2937,19 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa // If we establish a clip at all, then go ahead and make sure our background // rect is intersected with our layer's bounds. - if (ShadowData* boxShadow = renderer()->style()->boxShadow()) { + // FIXME: This could be changed to just use generic visual overflow. + // See https://bugs.webkit.org/show_bug.cgi?id=37467 for more information. + if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) { IntRect overflow = layerBounds; do { - if (boxShadow->style == Normal) { + if (boxShadow->style() == Normal) { IntRect shadowRect = layerBounds; - shadowRect.move(boxShadow->x, boxShadow->y); - shadowRect.inflate(boxShadow->blur + boxShadow->spread); + shadowRect.move(boxShadow->x(), boxShadow->y()); + shadowRect.inflate(boxShadow->blur() + boxShadow->spread()); overflow.unite(shadowRect); } - boxShadow = boxShadow->next; + boxShadow = boxShadow->next(); } while (boxShadow); backgroundRect.intersect(overflow); } else @@ -2987,7 +3050,7 @@ IntRect RenderLayer::localBoundingBox() const int top = firstBox->topVisibleOverflow(); int bottom = inlineFlow->lastLineBox()->bottomVisibleOverflow(); int left = firstBox->x(); - for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox()) left = min(left, curr->x()); result = IntRect(left, top, width(), bottom - top); } else if (renderer()->isTableRow()) { @@ -3160,22 +3223,33 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR // Locate the common ancestor render object for the two renderers. RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj); + Vector<RefPtr<Node>, 32> nodesToRemoveFromChain; + Vector<RefPtr<Node>, 32> nodesToAddToChain; + if (oldHoverObj != newHoverObj) { // The old hover path only needs to be cleared up to (and not including) the common ancestor; for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { - if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) { - curr->node()->setActive(false); - curr->node()->setHovered(false); - } + if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) + nodesToRemoveFromChain.append(curr->node()); } } // Now set the hover state for our new object up to the root. for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { - if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) { - curr->node()->setActive(request.active()); - curr->node()->setHovered(true); - } + if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) + nodesToAddToChain.append(curr->node()); + } + + size_t removeCount = nodesToRemoveFromChain.size(); + for (size_t i = 0; i < removeCount; ++i) { + nodesToRemoveFromChain[i]->setActive(false); + nodesToRemoveFromChain[i]->setHovered(false); + } + + size_t addCount = nodesToAddToChain.size(); + for (size_t i = 0; i < addCount; ++i) { + nodesToAddToChain[i]->setActive(request.active()); + nodesToAddToChain[i]->setHovered(true); } } @@ -3519,7 +3593,7 @@ void showLayerTree(const WebCore::RenderLayer* layer) return; if (WebCore::Frame* frame = layer->renderer()->document()->frame()) { - WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers); + WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses); fprintf(stderr, "%s\n", output.utf8().data()); } } diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 2c8d184..746c6fa 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -227,6 +227,8 @@ public: int width() const { return m_width; } int height() const { return m_height; } + IntSize size() const { return IntSize(m_width, m_height); } + void setWidth(int w) { m_width = w; } void setHeight(int h) { m_height = h; } @@ -237,8 +239,7 @@ public: // Scrolling methods for layers that can scroll their overflow. void scrollByRecursively(int xDelta, int yDelta); - void addScrolledContentOffset(int& x, int& y) const; - void subtractScrolledContentOffset(int& x, int& y) const; + IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset()); } int scrollXOffset() const { return m_scrollX + m_scrollOriginX; } @@ -304,7 +305,7 @@ public: UpdateCompositingLayers = 1 << 3, }; typedef unsigned UpdateLayerPositionsFlags; - void updateLayerPositions(UpdateLayerPositionsFlags = DoFullRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers); + void updateLayerPositions(UpdateLayerPositionsFlags = DoFullRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers, IntPoint* cachedOffset = 0); void updateTransform(); @@ -402,6 +403,7 @@ public: // Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint. IntRect repaintRect() const { return m_repaintRect; } void computeRepaintRects(); + void updateRepaintRectsAfterScroll(bool fixed = false); void setNeedsFullRepaint(bool f = true) { m_needsFullRepaint = f; } int staticX() const { return m_staticX; } diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index f637e3c..b5f74c6 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -424,7 +424,7 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs if (needsDescendantClip) { if (!m_clippingLayer) { - m_clippingLayer = GraphicsLayer::create(0); + m_clippingLayer = GraphicsLayer::create(this); #ifndef NDEBUG m_clippingLayer->setName("Child clipping Layer"); #endif diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index 7aea926..a6907e7 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -46,7 +46,7 @@ class RenderLayerCompositor; // // There is one RenderLayerBacking for each RenderLayer that is composited. -class RenderLayerBacking : public GraphicsLayerClient { +class RenderLayerBacking : public GraphicsLayerClient, public Noncopyable { public: RenderLayerBacking(RenderLayer*); ~RenderLayerBacking(); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index 22118fe..480abb7 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 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 @@ -37,8 +37,13 @@ #include "GraphicsLayer.h" #include "HitTestResult.h" #include "HTMLCanvasElement.h" +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "HTMLMediaElement.h" +#include "HTMLNames.h" +#endif #include "Page.h" #include "RenderEmbeddedObject.h" +#include "RenderIFrame.h" #include "RenderLayerBacking.h" #include "RenderReplica.h" #include "RenderVideo.h" @@ -50,7 +55,6 @@ #endif #ifndef NDEBUG -#include "CString.h" #include "RenderTreeAsText.h" #endif @@ -119,6 +123,8 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) ensureRootPlatformLayer(); else destroyRootPlatformLayer(); + + m_renderView->compositingStateChanged(m_compositing); } } @@ -134,6 +140,15 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags() showRepaintCounter = settings->showRepaintCounter(); } + // We allow the chrome to override the settings, in case the page is rendered + // on a chrome that doesn't allow accelerated compositing. + if (hasAcceleratedCompositing) { + Frame* frame = m_renderView->frameView()->frame(); + Page* page = frame ? frame->page() : 0; + if (page) + hasAcceleratedCompositing = page->chrome()->client()->allowsAcceleratedCompositing(); + } + if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter) setCompositingLayersNeedRebuild(); @@ -215,8 +230,13 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update rebuildCompositingLayerTree(updateRoot, compState, childList); // Host the document layer in the RenderView's root layer. - if (updateRoot == rootRenderLayer() && !childList.isEmpty()) - m_rootPlatformLayer->setChildren(childList); + if (updateRoot == rootRenderLayer()) { + if (childList.isEmpty()) { + willMoveOffscreen(); + m_rootPlatformLayer = 0; + } else + m_rootPlatformLayer->setChildren(childList); + } } else if (needGeometryUpdate) { // We just need to do a geometry update. This is only used for position:fixed scrolling; // most of the time, geometry is updated via RenderLayer::styleChanged(). @@ -326,7 +346,7 @@ void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) // RenderLayers that are rendered by the composited RenderLayer. IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) { - if (!layer->isSelfPaintingLayer()) + if (!canBeComposited(layer)) return IntRect(); IntRect boundingBoxRect, unionBounds; @@ -444,6 +464,9 @@ void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* if (!boundsComputed) { layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); + // Empty rects never intersect, but we need them to for the purposes of overlap testing. + if (layerBounds.isEmpty()) + layerBounds.setSize(IntSize(1, 1)); boundsComputed = true; } @@ -487,6 +510,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (overlapMap && !overlapMap->isEmpty()) { // If we're testing for overlap, we only need to composite if we overlap something that is already composited. absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); + // Empty rects never intersect, but we need them to for the purposes of overlap testing. + if (absBounds.isEmpty()) + absBounds.setSize(IntSize(1, 1)); haveComputedBounds = true; mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); } @@ -501,6 +527,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O ++childState.m_depth; #endif +<<<<<<< HEAD const bool willBeComposited = needsToBeComposited(layer); #if ENABLE(COMPOSITED_FIXED_ELEMENTS) @@ -513,6 +540,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (willBeComposited || compositingState.m_fixedSibling) { #else +======= + bool willBeComposited = needsToBeComposited(layer); +>>>>>>> webkit.org at r58033 if (willBeComposited) { #endif // Tell the parent it has compositing descendants. @@ -599,28 +629,44 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O // If we have a software transform, and we have layers under us, we need to also // be composited. Also, if we have opacity < 1, then we need to be a layer so that // the child layers are opaque, then rendered with opacity on this layer. - if (!willBeComposited && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { + if (!willBeComposited && canBeComposited(layer) && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { layer->setMustOverlapCompositedLayers(true); if (overlapMap) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); + willBeComposited = true; } + ASSERT(willBeComposited == needsToBeComposited(layer)); if (layer->reflectionLayer()) - layer->reflectionLayer()->setMustOverlapCompositedLayers(needsToBeComposited(layer)); + layer->reflectionLayer()->setMustOverlapCompositedLayers(willBeComposited); // Subsequent layers in the parent stacking context also need to composite. if (childState.m_subtreeIsCompositing) compositingState.m_subtreeIsCompositing = true; - // If the layer is going into compositing mode, repaint its old location. - if (!layer->isComposited() && needsToBeComposited(layer)) - repaintOnCompositingChange(layer); - // Set the flag to say that this SC has compositing children. - // this can affect the answer to needsToBeComposited() when clipping, - // but that's ok here. layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing); + // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, + // so test that again. + if (!willBeComposited && canBeComposited(layer) && clipsCompositingDescendants(layer)) { + if (overlapMap) + addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); + willBeComposited = true; + } + + // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need + // to be composited, then we can drop out of compositing mode altogether. + if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer)) { + m_compositing = false; + willBeComposited = false; + } + + // If the layer is going into compositing mode, repaint its old location. + ASSERT(willBeComposited == needsToBeComposited(layer)); + if (!layer->isComposited() && willBeComposited) + repaintOnCompositingChange(layer); + // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree(). if (updateBacking(layer, CompositingChangeRepaintNow)) layersChanged = true; @@ -967,9 +1013,10 @@ bool RenderLayerCompositor::has3DContent() const bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const { - if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer()) + if (!canBeComposited(layer)) return false; +<<<<<<< HEAD #if ENABLE(COMPOSITED_FIXED_ELEMENTS) // if an ancestor is fixed positioned, we need to be composited... const RenderLayer* currLayer = layer; @@ -980,6 +1027,9 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const #endif return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers(); +======= + return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers() || (inCompositingMode() && layer->isRootLayer()); +>>>>>>> webkit.org at r58033 } #if PLATFORM(ANDROID) @@ -1032,6 +1082,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c layer = toRenderBoxModelObject(renderer)->layer(); } // The root layer always has a compositing layer, but it may not have backing. +<<<<<<< HEAD return (inCompositingMode() && layer->isRootLayer()) || #if PLATFORM(ANDROID) requiresCompositingForMobileSites(layer) || @@ -1044,6 +1095,21 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c #endif renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden || clipsCompositingDescendants(layer); +======= + return requiresCompositingForTransform(renderer) + || requiresCompositingForVideo(renderer) + || requiresCompositingForCanvas(renderer) + || requiresCompositingForPlugin(renderer) + || requiresCompositingForIFrame(renderer) + || renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden + || clipsCompositingDescendants(layer) + || requiresCompositingForAnimation(renderer); +} + +bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const +{ + return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer(); +>>>>>>> webkit.org at r58033 } // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, @@ -1106,6 +1172,19 @@ bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) RenderVideo* video = toRenderVideo(renderer); return canAccelerateVideoRendering(video); } +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + else if (renderer->isRenderPart()) { + if (!m_hasAcceleratedCompositing) + return false; + + Node* node = renderer->node(); + if (!node || (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))) + return false; + + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); + return mediaElement->player() ? mediaElement->player()->supportsAcceleratedRendering() : false; + } +#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) #else UNUSED_PARAM(renderer); #endif @@ -1130,6 +1209,11 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing(); } +bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer) const +{ + return renderer->isRenderIFrame() && toRenderIFrame(renderer)->requiresAcceleratedCompositing(); +} + bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const { if (AnimationController* animController = renderer->animation()) { diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index eeacdf7..43b8a17 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -142,6 +142,8 @@ private: bool needsToBeComposited(const RenderLayer*) const; // Whether the layer has an intrinsic need for compositing layer. bool requiresCompositingLayer(const RenderLayer*) const; + // Whether the layer could ever be composited. + bool canBeComposited(const RenderLayer*) const; // Make or destroy the backing for this layer; returns true if backing changed. bool updateBacking(RenderLayer*, CompositingChangeRepaint shouldRepaint); @@ -179,6 +181,7 @@ private: bool requiresCompositingForVideo(RenderObject*) const; bool requiresCompositingForCanvas(RenderObject*) const; bool requiresCompositingForPlugin(RenderObject*) const; + bool requiresCompositingForIFrame(RenderObject*) const; bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const; #if PLATFORM(ANDROID) diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 57bc26c..9736874 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -67,7 +67,7 @@ void RenderLineBoxList::deleteLineBoxTree(RenderArena* arena) InlineFlowBox* line = m_firstLineBox; InlineFlowBox* nextLine; while (line) { - nextLine = line->nextFlowBox(); + nextLine = line->nextLineBox(); line->deleteLine(arena); line = nextLine; } @@ -78,13 +78,13 @@ void RenderLineBoxList::extractLineBox(InlineFlowBox* box) { checkConsistency(); - m_lastLineBox = box->prevFlowBox(); + m_lastLineBox = box->prevLineBox(); if (box == m_firstLineBox) m_firstLineBox = 0; if (box->prevLineBox()) box->prevLineBox()->setNextLineBox(0); box->setPreviousLineBox(0); - for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = box; curr; curr = curr->nextLineBox()) curr->setExtracted(); checkConsistency(); @@ -100,7 +100,7 @@ void RenderLineBoxList::attachLineBox(InlineFlowBox* box) } else m_firstLineBox = box; InlineFlowBox* last = box; - for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) { + for (InlineFlowBox* curr = box; curr; curr = curr->nextLineBox()) { curr->setExtracted(false); last = curr; } @@ -114,9 +114,9 @@ void RenderLineBoxList::removeLineBox(InlineFlowBox* box) checkConsistency(); if (box == m_firstLineBox) - m_firstLineBox = box->nextFlowBox(); + m_firstLineBox = box->nextLineBox(); if (box == m_lastLineBox) - m_lastLineBox = box->prevFlowBox(); + m_lastLineBox = box->prevLineBox(); if (box->nextLineBox()) box->nextLineBox()->setPreviousLineBox(box->prevLineBox()); if (box->prevLineBox()) @@ -128,8 +128,8 @@ void RenderLineBoxList::removeLineBox(InlineFlowBox* box) void RenderLineBoxList::deleteLineBoxes(RenderArena* arena) { if (m_firstLineBox) { - InlineRunBox* next; - for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) { + InlineFlowBox* next; + for (InlineFlowBox* curr = m_firstLineBox; curr; curr = next) { next = curr->nextLineBox(); curr->destroy(arena); } @@ -140,7 +140,7 @@ void RenderLineBoxList::deleteLineBoxes(RenderArena* arena) void RenderLineBoxList::dirtyLineBoxes() { - for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) curr->dirtyLineBoxes(); } @@ -177,7 +177,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain // based off positions of our first line box or our last line box. RenderView* v = renderer->view(); bool usePrintRect = !v->printRect().isEmpty(); - for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { + for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (usePrintRect) { // FIXME: This is a feeble effort to avoid splitting a line across two pages. // It is utterly inadequate, and this should not be done at paint time at all. @@ -236,7 +236,7 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. - for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) { + for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { @@ -281,9 +281,9 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend if (textBox) box = textBox->root(); } else if (curr->isRenderInline()) { - InlineRunBox* runBox = toRenderInline(curr)->lastLineBox(); - if (runBox) - box = runBox->root(); + InlineFlowBox* flowBox = toRenderInline(curr)->lastLineBox(); + if (flowBox) + box = flowBox->root(); } if (box) @@ -321,8 +321,8 @@ void RenderLineBoxList::checkConsistency() const { #ifdef CHECK_CONSISTENCY const InlineFlowBox* prev = 0; - for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) { - ASSERT(child->prevFlowBox() == prev); + for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextLineBox()) { + ASSERT(child->prevLineBox() == prev); prev = child; } ASSERT(prev == m_lastLineBox); diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index 54a7dd2..f861467 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -80,33 +80,24 @@ static bool isList(Node* node) return (node->hasTagName(ulTag) || node->hasTagName(olTag)); } -static Node* enclosingList(Node* node) +static Node* enclosingList(const RenderListItem* listItem) { - Node* parent = node->parentNode(); - for (Node* n = parent; n; n = n->parentNode()) - if (isList(n)) - return n; - // If there's no actual <ul> or <ol> list element, then our parent acts as - // our list for purposes of determining what other list items should be - // numbered as part of the same list. - return parent; -} - -static Node* enclosingList(const RenderObject* renderer) -{ - Node* node = renderer->node(); - if (node) - return enclosingList(node); - - renderer = renderer->parent(); - while (renderer && !renderer->node()) - renderer = renderer->parent(); - - node = renderer->node(); - if (isList(node)) - return node; + Node* firstNode = 0; + + for (const RenderObject* renderer = listItem->parent(); renderer; renderer = renderer->parent()) { + Node* node = renderer->node(); + if (node) { + if (isList(node)) + return node; + if (!firstNode) + firstNode = node; + } + } - return enclosingList(node); + // If there's no actual <ul> or <ol> list element, then the first found + // node acts as our list for purposes of determining what other list items + // should be numbered as part of the same list. + return firstNode; } static RenderListItem* previousListItem(Node* list, const RenderListItem* item) @@ -114,7 +105,7 @@ static RenderListItem* previousListItem(Node* list, const RenderListItem* item) for (RenderObject* renderer = item->previousInPreOrder(); renderer != list->renderer(); renderer = renderer->previousInPreOrder()) { if (!renderer->isListItem()) continue; - Node* otherList = enclosingList(renderer); + Node* otherList = enclosingList(toRenderListItem(renderer)); // This item is part of our current list, so it's what we're looking for. if (list == otherList) return toRenderListItem(renderer); @@ -326,7 +317,7 @@ void RenderListItem::explicitValueChanged() { if (m_marker) m_marker->setNeedsLayoutAndPrefWidthsRecalc(); - Node* listNode = enclosingList(node()); + Node* listNode = enclosingList(this); RenderObject* listRenderer = 0; if (listNode) listRenderer = listNode->renderer(); @@ -364,4 +355,38 @@ void RenderListItem::clearExplicitValue() explicitValueChanged(); } +void RenderListItem::updateListMarkerNumbers() +{ + Node* listNode = enclosingList(this); + ASSERT(listNode && listNode->renderer()); + if (!listNode || !listNode->renderer()) + return; + + RenderObject* list = listNode->renderer(); + RenderObject* child = nextInPreOrder(list); + while (child) { + if (child->node() && isList(child->node())) { + // We've found a nested, independent list: nothing to do here. + child = child->nextInPreOrderAfterChildren(list); + continue; + } + + if (child->isListItem()) { + RenderListItem* item = toRenderListItem(child); + + if (!item->m_isValueUpToDate) { + // If an item has been marked for update before, we can safely + // assume that all the following ones have too. + // This gives us the opportunity to stop here and avoid + // marking the same nodes again. + break; + } + + item->updateValue(); + } + + child = child->nextInPreOrder(list); + } +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h index c4c41dc..2ad9a41 100644 --- a/WebCore/rendering/RenderListItem.h +++ b/WebCore/rendering/RenderListItem.h @@ -46,6 +46,8 @@ public: const String& markerText() const; + void updateListMarkerNumbers(); + private: virtual const char* renderName() const { return "RenderListItem"; } diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index 05a9873..518925a 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -1,6 +1,7 @@ /* * This file is part of the select element renderer in WebCore. * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * @@ -25,6 +26,7 @@ #include "RenderMenuList.h" #include "AXObjectCache.h" +#include "AccessibilityObject.h" #include "CSSStyleSelector.h" #include "Frame.h" #include "FrameView.h" @@ -308,6 +310,20 @@ void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange) select->setSelectedIndexByUser(select->listToOptionIndex(listIndex), true, fireOnChange); } +#if ENABLE(NO_LISTBOX_RENDERING) +void RenderMenuList::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow) +{ + SelectElement* select = toSelectElement(static_cast<Element*>(node())); + select->listBoxSelectItem(select->listToOptionIndex(listIndex), allowMultiplySelections, shift, fireOnChangeNow); +} + +bool RenderMenuList::multiple() +{ + SelectElement* select = toSelectElement(static_cast<Element*>(node())); + return select->multiple(); +} +#endif + void RenderMenuList::didSetSelectedIndex() { int index = selectedIndex(); @@ -334,6 +350,17 @@ String RenderMenuList::itemText(unsigned listIndex) const return String(); } +String RenderMenuList::itemAccessibilityText(unsigned listIndex) const +{ + // Allow the accessible name be changed if necessary. + SelectElement* select = toSelectElement(static_cast<Element*>(node())); + const Vector<Element*>& listItems = select->listItems(); + if (listIndex >= listItems.size()) + return String(); + + return AccessibilityObject::getAttribute(listItems[listIndex], aria_labelAttr); +} + String RenderMenuList::itemToolTip(unsigned listIndex) const { SelectElement* select = toSelectElement(static_cast<Element*>(node())); diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h index a5aa041..aeb6205 100644 --- a/WebCore/rendering/RenderMenuList.h +++ b/WebCore/rendering/RenderMenuList.h @@ -1,6 +1,7 @@ /* * This file is part of the select element renderer in WebCore. * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -37,7 +38,12 @@ namespace WebCore { class PopupMenu; class RenderText; +#if ENABLE(NO_LISTBOX_RENDERING) +class RenderMenuList : public RenderFlexibleBox, private ListPopupMenuClient { +#else class RenderMenuList : public RenderFlexibleBox, private PopupMenuClient { +#endif + public: RenderMenuList(Element*); virtual ~RenderMenuList(); @@ -75,6 +81,7 @@ private: // PopupMenuClient methods virtual String itemText(unsigned listIndex) const; virtual String itemToolTip(unsigned listIndex) const; + virtual String itemAccessibilityText(unsigned listIndex) const; virtual bool itemIsEnabled(unsigned listIndex) const; virtual PopupMenuStyle itemStyle(unsigned listIndex) const; virtual PopupMenuStyle menuStyle() const; @@ -96,6 +103,11 @@ private: virtual HostWindow* hostWindow() const; virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize); +#if ENABLE(NO_LISTBOX_RENDERING) + virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true); + virtual bool multiple(); +#endif + virtual bool hasLineIfEmpty() const { return true; } Color itemBackgroundColor(unsigned listIndex) const; diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index e70de96..d63997a 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -119,12 +119,12 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) if (node->hasTagName(rubyTag)) { if (style->display() == INLINE) return new (arena) RenderRubyAsInline(node); - else + else if (style->display() == BLOCK) return new (arena) RenderRubyAsBlock(node); } // 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); + return new (arena) RenderRubyText(node); #endif switch (style->display()) { @@ -260,14 +260,6 @@ bool RenderObject::isHTMLMarquee() const return node() && node()->renderer() == this && node()->hasTagName(marqueeTag); } -static void updateListMarkerNumbers(RenderObject* child) -{ - for (RenderObject* sibling = child; sibling; sibling = sibling->nextSibling()) { - if (sibling->isListItem()) - toRenderListItem(sibling)->updateValue(); - } -} - void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) { RenderObjectChildList* children = virtualChildren(); @@ -277,9 +269,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) bool needsTable = false; - if (newChild->isListItem()) - updateListMarkerNumbers(beforeChild ? beforeChild : children->lastChild()); - else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP) + if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP) needsTable = !isTable(); else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION) needsTable = !isTable(); @@ -701,7 +691,7 @@ bool RenderObject::mustRepaintBackgroundOrBorder() const } void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, - BoxSide s, Color c, const Color& textcolor, EBorderStyle style, + BoxSide s, Color c, EBorderStyle style, int adjbw1, int adjbw2) { int width = (s == BSTop || s == BSBottom ? y2 - y1 : x2 - x1); @@ -709,13 +699,6 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, if (style == DOUBLE && width < 3) style = SOLID; - if (!c.isValid()) { - if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE) - c.setRGB(238, 238, 238); - else - c = textcolor; - } - switch (style) { case BNONE: case BHIDDEN: @@ -767,34 +750,34 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, case BSTop: drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0), y1, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y1 + third, - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0), y2 - third, x2 - max((adjbw2 * 2 + 1) / 3, 0), y2, - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); break; case BSLeft: drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0), x1 + third, y2 - max((-adjbw2 * 2 + 1) / 3, 0), - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0), x2, y2 - max((adjbw2 * 2 + 1) / 3, 0), - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); break; case BSBottom: drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0), y1, x2 - max((adjbw2 * 2 + 1) / 3, 0), y1 + third, - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0), y2 - third, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y2, - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); break; case BSRight: drawLineForBoxSide(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0), x1 + third, y2 - max((adjbw2 * 2 + 1) / 3, 0), - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0), x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0), - s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird); + s, c, SOLID, adjbw1bigthird, adjbw2bigthird); break; default: break; @@ -821,27 +804,27 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, switch (s) { case BSTop: drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2, - s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf); + s, c, s1, adjbw1bighalf, adjbw2bighalf); drawLineForBoxSide(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2, - s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2); + s, c, s2, adjbw1 / 2, adjbw2 / 2); break; case BSLeft: drawLineForBoxSide(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2, - s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf); + s, c, s1, adjbw1bighalf, adjbw2bighalf); drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2, - s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2); + s, c, s2, adjbw1 / 2, adjbw2 / 2); break; case BSBottom: drawLineForBoxSide(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2, - s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf); + s, c, s2, adjbw1bighalf, adjbw2bighalf); drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2, - s, c, textcolor, s1, adjbw1/2, adjbw2/2); + s, c, s1, adjbw1 / 2, adjbw2 / 2); break; case BSRight: drawLineForBoxSide(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2, - s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf); + s, c, s2, adjbw1bighalf, adjbw2bighalf); drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2, - s, c, textcolor, s1, adjbw1/2, adjbw2/2); + s, c, s1, adjbw1 / 2, adjbw2 / 2); break; } break; @@ -897,19 +880,12 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, } void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, int y, float thickness, IntSize radius, - int angleStart, int angleSpan, BoxSide s, Color c, const Color& textColor, + int angleStart, int angleSpan, BoxSide s, Color c, EBorderStyle style, bool firstCorner) { if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2)) style = SOLID; - if (!c.isValid()) { - if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE) - c.setRGB(238, 238, 238); - else - c = textColor; - } - switch (style) { case BNONE: case BHIDDEN: @@ -997,33 +973,32 @@ void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect) context->setURLForRect(n->document()->completeURL(href), rect); } -void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style) +void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h) { if (!hasOutline()) return; - int ow = style->outlineWidth(); - EBorderStyle os = style->outlineStyle(); + RenderStyle* styleToUse = style(); + int ow = styleToUse->outlineWidth(); + EBorderStyle os = styleToUse->outlineStyle(); - Color oc = style->outlineColor(); - if (!oc.isValid()) - oc = style->color(); + Color oc = styleToUse->visitedDependentColor(CSSPropertyOutlineColor); - int offset = style->outlineOffset(); + int offset = styleToUse->outlineOffset(); - if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) { - if (!theme()->supportsFocusRing(style)) { + if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) { + if (!theme()->supportsFocusRing(styleToUse)) { // Only paint the focus ring by hand if the theme isn't able to draw the focus ring. Vector<IntRect> focusRingRects; addFocusRingRects(focusRingRects, tx, ty); - if (style->outlineStyleIsAuto()) + if (styleToUse->outlineStyleIsAuto()) graphicsContext->drawFocusRing(focusRingRects, ow, offset, oc); else addPDFURLRect(graphicsContext, unionRect(focusRingRects)); } } - if (style->outlineStyleIsAuto() || style->outlineStyle() == BNONE) + if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE) return; tx -= offset; @@ -1034,17 +1009,10 @@ void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty if (h < 0 || w < 0) return; - drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow, - BSLeft, Color(oc), style->color(), os, ow, ow); - - drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty, - BSTop, Color(oc), style->color(), os, ow, ow); - - drawLineForBoxSide(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow, - BSRight, Color(oc), style->color(), os, ow, ow); - - drawLineForBoxSide(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow, - BSBottom, Color(oc), style->color(), os, ow, ow); + drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow, BSLeft, oc, os, ow, ow); + drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty, BSTop, oc, os, ow, ow); + drawLineForBoxSide(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow, BSRight, oc, os, ow, ow); + drawLineForBoxSide(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow, BSBottom, oc, os, ow, ow); } IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms) @@ -1182,13 +1150,14 @@ void RenderObject::repaintRectangle(const IntRect& r, bool immediate) repaintUsingContainer(repaintContainer ? repaintContainer : view, dirtyRect, immediate); } -bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox) +bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox, const IntRect* newBoundsPtr, const IntRect* newOutlineBoxRectPtr) { RenderView* v = view(); if (v->printing()) return false; // Don't repaint if we're printing. - IntRect newBounds = clippedOverflowRectForRepaint(repaintContainer); + ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer)); + IntRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer); IntRect newOutlineBox; bool fullRepaint = selfNeedsLayout(); @@ -1196,7 +1165,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta if (!fullRepaint && style()->borderFit() == BorderFitLines) fullRepaint = true; if (!fullRepaint) { - newOutlineBox = outlineBoundsForRepaint(repaintContainer); + ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer)); + newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer); if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox))) fullRepaint = true; } @@ -1331,11 +1301,10 @@ void RenderObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, // anyway if its size does change. RenderBox* boxParent = toRenderBox(o); + IntRect repaintRect(rect); + repaintRect.move(-boxParent->layer()->scrolledContentOffset()); // For overflow:auto/scroll/hidden. + IntRect boxRect(0, 0, boxParent->layer()->width(), boxParent->layer()->height()); - int x = rect.x(); - int y = rect.y(); - boxParent->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden. - IntRect repaintRect(x, y, rect.width(), rect.height()); rect = intersection(repaintRect, boxRect); if (rect.isEmpty()) return; @@ -1667,9 +1636,10 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS #endif bool newStyleSlowScroll = newStyle && (newStyle->position() == FixedPosition - || (!shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage())); + || (!shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage())); bool oldStyleSlowScroll = m_style && (m_style->position() == FixedPosition - || (!shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage())); + || (!shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage())); + if (oldStyleSlowScroll != newStyleSlowScroll) { if (oldStyleSlowScroll) view()->frameView()->removeSlowRepaintObject(); @@ -2210,21 +2180,17 @@ PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(PseudoId pseudo, Re return result.release(); } -static Color decorationColor(RenderStyle* style) +static Color decorationColor(RenderObject* renderer) { Color result; - if (style->textStrokeWidth() > 0) { + if (renderer->style()->textStrokeWidth() > 0) { // Prefer stroke color if possible but not if it's fully transparent. - result = style->textStrokeColor(); - if (!result.isValid()) - result = style->color(); + result = renderer->style()->visitedDependentColor(CSSPropertyWebkitTextStrokeColor); if (result.alpha()) return result; } - result = style->textFillColor(); - if (!result.isValid()) - result = style->color(); + result = renderer->style()->visitedDependentColor(CSSPropertyWebkitTextFillColor); return result; } @@ -2237,15 +2203,15 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co if (currDecs) { if (currDecs & UNDERLINE) { decorations &= ~UNDERLINE; - underline = decorationColor(curr->style()); + underline = decorationColor(curr); } if (currDecs & OVERLINE) { decorations &= ~OVERLINE; - overline = decorationColor(curr->style()); + overline = decorationColor(curr); } if (currDecs & LINE_THROUGH) { decorations &= ~LINE_THROUGH; - linethrough = decorationColor(curr->style()); + linethrough = decorationColor(curr); } } curr = curr->parent(); @@ -2257,11 +2223,11 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co // If we bailed out, use the element we bailed out at (typically a <font> or <a> element). if (decorations && curr) { if (decorations & UNDERLINE) - underline = decorationColor(curr->style()); + underline = decorationColor(curr); if (decorations & OVERLINE) - overline = decorationColor(curr->style()); + overline = decorationColor(curr); if (decorations & LINE_THROUGH) - linethrough = decorationColor(curr->style()); + linethrough = decorationColor(curr); } } @@ -2381,21 +2347,21 @@ int RenderObject::nextOffset(int current) const void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const { int outlineSize = outlineStyleForRepaint()->outlineSize(); - if (ShadowData* boxShadow = style()->boxShadow()) { + if (const ShadowData* boxShadow = style()->boxShadow()) { int shadowLeft = 0; int shadowRight = 0; int shadowTop = 0; int shadowBottom = 0; do { - if (boxShadow->style == Normal) { - shadowLeft = min(boxShadow->x - boxShadow->blur - boxShadow->spread - outlineSize, shadowLeft); - shadowRight = max(boxShadow->x + boxShadow->blur + boxShadow->spread + outlineSize, shadowRight); - shadowTop = min(boxShadow->y - boxShadow->blur - boxShadow->spread - outlineSize, shadowTop); - shadowBottom = max(boxShadow->y + boxShadow->blur + boxShadow->spread + outlineSize, shadowBottom); + if (boxShadow->style() == Normal) { + shadowLeft = min(boxShadow->x() - boxShadow->blur() - boxShadow->spread() - outlineSize, shadowLeft); + shadowRight = max(boxShadow->x() + boxShadow->blur() + boxShadow->spread() + outlineSize, shadowRight); + shadowTop = min(boxShadow->y() - boxShadow->blur() - boxShadow->spread() - outlineSize, shadowTop); + shadowBottom = max(boxShadow->y() + boxShadow->blur() + boxShadow->spread() + outlineSize, shadowBottom); } - boxShadow = boxShadow->next; + boxShadow = boxShadow->next(); } while (boxShadow); rect.move(shadowLeft, shadowTop); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 791d4d0..ae12758 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -277,8 +277,12 @@ public: virtual bool isListMarker() const { return false; } virtual bool isMedia() const { return false; } virtual bool isMenuList() const { return false; } +#if ENABLE(PROGRESS_TAG) + virtual bool isProgress() const { return false; } +#endif virtual bool isRenderBlock() const { return false; } virtual bool isRenderButton() const { return false; } + virtual bool isRenderIFrame() const { return false; } virtual bool isRenderImage() const { return false; } virtual bool isRenderInline() const { return false; } virtual bool isRenderPart() const { return false; } @@ -334,10 +338,17 @@ public: virtual bool isSVGImage() const { return false; } virtual bool isSVGForeignObject() const { return false; } virtual bool isSVGResource() const { return false; } + virtual bool isSVGShadowTreeRootContainer() const { return false; } virtual const SVGRenderBase* toSVGRenderBase() const; virtual RenderSVGResource* toRenderSVGResource(); + // FIXME: Those belong into a SVG specific base-class for all renderers (see above) + // Unfortunately we don't have such a class yet, because it's not possible for all renderers + // to inherit from RenderSVGObject -> RenderObject (some need RenderBlock inheritance for instance) + virtual void setNeedsTransformUpdate() { } + virtual void setNeedsBoundariesUpdate() { } + // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them @@ -350,7 +361,6 @@ public: // respecting clipping, masking, filters, opacity, stroke-width and markers virtual FloatRect repaintRectInLocalCoordinates() const; - // FIXME: This accessor is deprecated and mostly around for SVGRenderTreeAsText. // This only returns the transform="" value from the element // most callsites want localToParentTransform() instead. virtual AffineTransform localTransform() const; @@ -405,9 +415,9 @@ public: bool hasMask() const { return style() && style()->hasMask(); } void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide, - Color, const Color& textcolor, EBorderStyle, int adjbw1, int adjbw2); + Color, EBorderStyle, int adjbw1, int adjbw2); void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart, - int angleSpan, BoxSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner); + int angleSpan, BoxSide, Color, EBorderStyle, bool firstCorner); public: // The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect @@ -512,10 +522,6 @@ public: /* This function performs a layout only if one is needed. */ void layoutIfNeeded() { if (needsLayout()) layout(); } - - // Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted - // that just updates the object's position. If the size does change, the object remains dirty. - virtual void tryLayoutDoingPositionedMovementOnly() { } // used for element state updates that cannot be fixed with a // repaint and do not need a relayout @@ -616,8 +622,8 @@ public: // Repaint a specific subrectangle within a given object. The rect |r| is in the object's coordinate space. void repaintRectangle(const IntRect&, bool immediate = false); - // Repaint only if our old bounds and new bounds are different. - bool repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox); + // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known. + bool repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox, const IntRect* newBoundsPtr = 0, const IntRect* newOutlineBoxPtr = 0); // Repaint only if the object moved. virtual void repaintDuringLayoutIfMoved(const IntRect& rect); @@ -782,7 +788,7 @@ protected: // Overrides should call the superclass at the start virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); - void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*); + void paintOutline(GraphicsContext*, int tx, int ty, int w, int h); void addPDFURLRect(GraphicsContext*, const IntRect&); virtual IntRect viewRect() const; @@ -791,7 +797,7 @@ protected: void arenaDelete(RenderArena*, void* objectBase); - virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const { return IntRect(); } + virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/, IntPoint* /*cachedOffsetToRepaintContainer*/ = 0) const { return IntRect(); } class LayoutRepainter { public: diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp index d56a015..6d76f34 100644 --- a/WebCore/rendering/RenderObjectChildList.cpp +++ b/WebCore/rendering/RenderObjectChildList.cpp @@ -39,14 +39,6 @@ namespace WebCore { -static void updateListMarkerNumbers(RenderObject* child) -{ - for (RenderObject* sibling = child; sibling; sibling = sibling->nextSibling()) { - if (sibling->isListItem()) - toRenderListItem(sibling)->updateValue(); - } -} - void RenderObjectChildList::destroyLeftoverChildren() { while (firstChild()) { @@ -91,11 +83,10 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render layer = owner->enclosingLayer(); oldChild->removeLayers(layer); } - - // renumber ordered lists + if (oldChild->isListItem()) - updateListMarkerNumbers(oldChild->nextSibling()); - + toRenderListItem(oldChild)->updateListMarkerNumbers(); + if (oldChild->isPositioned() && owner->childrenInline()) owner->dirtyLinesFromChangedChild(oldChild); } @@ -161,7 +152,10 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n if (layer) layer->setHasVisibleContent(true); } - + + if (newChild->isListItem()) + toRenderListItem(newChild)->updateListMarkerNumbers(); + if (!newChild->isFloatingOrPositioned() && owner->childrenInline()) owner->dirtyLinesFromChangedChild(newChild); } @@ -218,7 +212,9 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c layer->setHasVisibleContent(true); } - + if (child->isListItem()) + toRenderListItem(child)->updateListMarkerNumbers(); + if (!child->isFloating() && owner->childrenInline()) owner->dirtyLinesFromChangedChild(child); } @@ -234,17 +230,42 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c static RenderObject* beforeAfterContainer(RenderObject* container, PseudoId type) { if (type == BEFORE) { + // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent. + // Therefore we should skip these generated run-ins when checking our immediate children. + // If we don't find our :before child immediately, then we should check if we own a + // generated inline run-in in the next level of children. RenderObject* first = container; do { - // Skip list markers. + // Skip list markers and generated run-ins first = first->firstChild(); - while (first && first->isListMarker()) + while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn() && first->isAnonymous()))) first = first->nextSibling(); } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO); - if (first && first->style()->styleType() != type) + + if (!first) + return 0; + + if (first->style()->styleType() == type) + return first; + + // Check for a possible generated run-in, using run-in positioning rules. + // Skip inlines and floating / positioned blocks, and place as the first child. + first = container->firstChild(); + if (!first->isRenderBlock()) return 0; - return first; + while (first && first->isFloatingOrPositioned()) + first = first->nextSibling(); + if (first) { + first = first->firstChild(); + // We still need to skip any list markers that could exist before the run-in. + while (first && first->isListMarker()) + first = first->nextSibling(); + if (first && first->style()->styleType() == type && first->isRenderInline() && first->isRunIn() && first->isAnonymous()) + return first; + } + return 0; } + if (type == AFTER) { RenderObject* last = container; do { @@ -314,7 +335,7 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo // Whether or not we currently have generated content attached. bool oldContentPresent = child; - // Whether or not we now want generated content. + // Whether or not we now want generated content. bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE; // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate @@ -330,9 +351,9 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo // If we don't want generated content any longer, or if we have generated content, but it's no longer // identical to the new content data we want to build render objects for, then we nuke all // of the old generated content. - if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) { + if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) { // Nuke the child. - if (child && child->style()->styleType() == type) { + if (child->style()->styleType() == type) { oldContentPresent = false; child->destroy(); child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild(); diff --git a/WebCore/rendering/RenderPart.cpp b/WebCore/rendering/RenderPart.cpp index 5c4a6ec..3262961 100644 --- a/WebCore/rendering/RenderPart.cpp +++ b/WebCore/rendering/RenderPart.cpp @@ -24,16 +24,16 @@ #include "config.h" #include "RenderPart.h" +#include "RenderView.h" #include "Frame.h" #include "FrameView.h" +#include "HTMLFrameElementBase.h" namespace WebCore { RenderPart::RenderPart(Element* node) : RenderWidget(node) - , m_hasFallbackContent(false) { - // init RenderObject attributes setInline(false); } diff --git a/WebCore/rendering/RenderPart.h b/WebCore/rendering/RenderPart.h index 8303543..18f2346 100644 --- a/WebCore/rendering/RenderPart.h +++ b/WebCore/rendering/RenderPart.h @@ -27,23 +27,15 @@ namespace WebCore { -// Renderer for frames via RenderPartObject, and plug-ins via RenderEmbeddedObject. - -// FIXME: This class is subclassed in RenderPartObject for iframes, which is in turn -// subclassed in RenderEmbeddedObject for object and embed. This class itself could be removed. +// Renderer for frames via RenderFrameBase, and plug-ins via RenderEmbeddedObject. class RenderPart : public RenderWidget { public: RenderPart(Element*); virtual ~RenderPart(); - - bool hasFallbackContent() const { return m_hasFallbackContent; } virtual void setWidget(PassRefPtr<Widget>); virtual void viewCleared(); -protected: - bool m_hasFallbackContent; - private: virtual bool isRenderPart() const { return true; } virtual const char* renderName() const { return "RenderPart"; } diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index bcedd38..b1e2a8f 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -31,10 +31,11 @@ #include "GraphicsContext.h" #include "PointerEventsHitRules.h" #include "RenderSVGContainer.h" +#include "RenderSVGResourceFilter.h" +#include "RenderSVGResourceMarker.h" #include "StrokeStyleApplier.h" #include "SVGPaintServer.h" #include "SVGRenderSupport.h" -#include "SVGResourceMarker.h" #include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" #include "SVGURIReference.h" @@ -64,19 +65,12 @@ private: RenderPath::RenderPath(SVGStyledTransformableElement* node) : RenderSVGModelObject(node) + , m_needsBoundariesUpdate(false) // default is false, as this is only used when a RenderSVGResource tells us that the boundaries need to be recached + , m_needsPathUpdate(true) // default is true, so we grab a Path object once from SVGStyledTransformableElement + , m_needsTransformUpdate(true) // default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement { } -const AffineTransform& RenderPath::localToParentTransform() const -{ - return m_localTransform; -} - -AffineTransform RenderPath::localTransform() const -{ - return m_localTransform; -} - bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const { if (m_path.isEmpty()) @@ -171,22 +165,34 @@ FloatRect RenderPath::repaintRectInLocalCoordinates() const return m_cachedLocalRepaintRect; } -void RenderPath::setPath(const Path& newPath) -{ - m_path = newPath; - m_cachedLocalRepaintRect = FloatRect(); - m_cachedLocalStrokeBBox = FloatRect(); - m_cachedLocalFillBBox = FloatRect(); - m_cachedLocalMarkerBBox = FloatRect(); -} - void RenderPath::layout() { LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); - m_localTransform = element->animatedLocalTransform(); - setPath(element->toPathData()); + + // We need to update the Path object whenever the underlying SVGStyledTransformableElement uses relative values + // as the viewport size may have changed. It would be nice to optimize this to detect these changes, and only + // update when needed, even when using relative values. + if (!m_needsPathUpdate && element->hasRelativeValues()) + m_needsPathUpdate = true; + + bool needsUpdate = m_needsPathUpdate || m_needsTransformUpdate || m_needsBoundariesUpdate; + + if (m_needsBoundariesUpdate) + m_needsBoundariesUpdate = false; + + if (m_needsPathUpdate) { + m_path = element->toPathData(); + m_needsPathUpdate = false; + } + + if (m_needsTransformUpdate) { + m_localTransform = element->animatedLocalTransform(); + m_needsTransformUpdate = false; + } + + if (needsUpdate) + invalidateCachedBoundaries(); repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -223,29 +229,32 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int) return; PaintInfo childPaintInfo(paintInfo); - childPaintInfo.context->save(); - applyTransformToPaintInfo(childPaintInfo, m_localTransform); - SVGResourceFilter* filter = 0; - - if (childPaintInfo.phase == PaintPhaseForeground) { - PaintInfo savedInfo(childPaintInfo); - - if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) { - if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) - childPaintInfo.context->setShouldAntialias(false); - fillAndStrokePath(m_path, childPaintInfo.context, style(), this); - - if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) - m_markerLayoutInfo.drawMarkers(childPaintInfo); + bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline); + if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) { + childPaintInfo.context->save(); + applyTransformToPaintInfo(childPaintInfo, m_localTransform); + RenderSVGResourceFilter* filter = 0; + + if (childPaintInfo.phase == PaintPhaseForeground) { + PaintInfo savedInfo(childPaintInfo); + + if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) { + if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) + childPaintInfo.context->setShouldAntialias(false); + fillAndStrokePath(m_path, childPaintInfo.context, style(), this); + + if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) + m_markerLayoutInfo.drawMarkers(childPaintInfo); + } + finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context); } - finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context); - } - if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) - paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), - static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style()); - - childPaintInfo.context->restore(); + if (drawsOutline) + paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), + static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height())); + + childPaintInfo.context->restore(); + } } // This method is called from inside paintOutline() since we call paintOutline() @@ -293,28 +302,28 @@ void RenderPath::calculateMarkerBoundsIfNeeded() const return; const SVGRenderStyle* svgStyle = style()->svgStyle(); - AtomicString startMarkerId(svgStyle->startMarker()); - AtomicString midMarkerId(svgStyle->midMarker()); - AtomicString endMarkerId(svgStyle->endMarker()); + AtomicString startMarkerId(svgStyle->markerStartResource()); + AtomicString midMarkerId(svgStyle->markerMidResource()); + AtomicString endMarkerId(svgStyle->markerEndResource()); - SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId, this); - SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId, this); - SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId, this); + RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, startMarkerId); + RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, midMarkerId); + RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, endMarkerId); if (!startMarker && !startMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement); else if (startMarker) - startMarker->addClient(styledElement); + startMarker->addClient(this); if (!midMarker && !midMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement); else if (midMarker) - midMarker->addClient(styledElement); + midMarker->addClient(this); if (!endMarker && !endMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement); else if (endMarker) - endMarker->addClient(styledElement); + endMarker->addClient(this); if (!startMarker && !midMarker && !endMarker) return; @@ -323,6 +332,20 @@ void RenderPath::calculateMarkerBoundsIfNeeded() const m_cachedLocalMarkerBBox = m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path); } +void RenderPath::invalidateCachedBoundaries() +{ + m_cachedLocalRepaintRect = FloatRect(); + m_cachedLocalStrokeBBox = FloatRect(); + m_cachedLocalFillBBox = FloatRect(); + m_cachedLocalMarkerBBox = FloatRect(); +} + +void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +{ + invalidateCachedBoundaries(); + RenderSVGModelObject::styleWillChange(diff, newStyle); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index d530f3c..ea4de40 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -41,6 +41,9 @@ public: RenderPath(SVGStyledTransformableElement*); const Path& path() const { return m_path; } + void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } + void setNeedsPathUpdate() { m_needsPathUpdate = true; } + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: // Hit-detection seperated for the fill and the stroke @@ -52,9 +55,7 @@ private: virtual FloatRect markerBoundingBox() const; virtual FloatRect repaintRectInLocalCoordinates() const; - virtual const AffineTransform& localToParentTransform() const; - - void setPath(const Path&); + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } virtual bool isRenderPath() const { return true; } virtual const char* renderName() const { return "RenderPath"; } @@ -64,11 +65,17 @@ private: virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); + virtual void styleWillChange(StyleDifference, const RenderStyle*); void calculateMarkerBoundsIfNeeded() const; + void invalidateCachedBoundaries(); private: - virtual AffineTransform localTransform() const; + virtual AffineTransform localTransform() const { return m_localTransform; } + + bool m_needsBoundariesUpdate : 1; + bool m_needsPathUpdate : 1; + bool m_needsTransformUpdate : 1; mutable Path m_path; mutable FloatRect m_cachedLocalFillBBox; diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp new file mode 100644 index 0000000..a9dbfe8 --- /dev/null +++ b/WebCore/rendering/RenderProgress.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#if ENABLE(PROGRESS_TAG) + +#include "RenderProgress.h" + +#include "HTMLProgressElement.h" +#include "RenderTheme.h" +#include <wtf/CurrentTime.h> + +using namespace std; + +namespace WebCore { + +using namespace HTMLNames; + +RenderProgress::RenderProgress(HTMLProgressElement* element) + : RenderBlock(element) + , m_position(-1) + , m_animationStartTime(0) + , m_animationRepeatInterval(0) + , m_animationDuration(0) + , m_animating(false) + , m_animationTimer(this, &RenderProgress::animationTimerFired) +{ +} + +void RenderProgress::layout() +{ + ASSERT(needsLayout()); + + LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); + + calcWidth(); + calcHeight(); + + m_overflow.clear(); + + updateAnimationState(); + + repainter.repaintAfterLayout(); + + setNeedsLayout(false); +} + +void RenderProgress::updateFromElement() +{ + HTMLProgressElement* element = progressElement(); + if (m_position == element->position()) + return; + m_position = element->position(); + + updateAnimationState(); + + repaint(); +} + +double RenderProgress::animationProgress() +{ + return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0; +} + +void RenderProgress::animationTimerFired(Timer<RenderProgress>*) +{ + repaint(); +} + +void RenderProgress::paint(PaintInfo& paintInfo, int tx, int ty) +{ + if (paintInfo.phase == PaintPhaseBlockBackground) { + if (!m_animationTimer.isActive() && m_animating) + m_animationTimer.startOneShot(m_animationRepeatInterval); + } + + RenderBlock::paint(paintInfo, tx, ty); +} + +void RenderProgress::updateAnimationState() +{ + m_animationDuration = theme()->animationDurationForProgressBar(this); + m_animationRepeatInterval = theme()->animationRepeatIntervalForProgressBar(this); + + bool animating = m_animationDuration > 0; + if (animating == m_animating) + return; + + m_animating = animating; + if (m_animating) { + m_animationStartTime = currentTime(); + m_animationTimer.startOneShot(m_animationRepeatInterval); + } else + m_animationTimer.stop(); +} + +HTMLProgressElement* RenderProgress::progressElement() const +{ + return static_cast<HTMLProgressElement*>(node()); +} + +} // namespace WebCore +#endif diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h new file mode 100644 index 0000000..d6f5078 --- /dev/null +++ b/WebCore/rendering/RenderProgress.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderProgress_h +#define RenderProgress_h + +#if ENABLE(PROGRESS_TAG) +#include "RenderBlock.h" + +namespace WebCore { + +class HTMLProgressElement; + +class RenderProgress : public RenderBlock { +public: + RenderProgress(HTMLProgressElement*); + double position() { return m_position; } + double animationProgress(); + + HTMLProgressElement* progressElement() const; + +private: + virtual const char* renderName() const { return "RenderProgress"; } + virtual bool isProgress() const { return true; } + virtual void layout(); + virtual void updateFromElement(); + virtual void paint(PaintInfo&, int tx, int ty); + + void animationTimerFired(Timer<RenderProgress>*); + void updateAnimationState(); + + double m_position; + double m_animationStartTime; + double m_animationRepeatInterval; + double m_animationDuration; + bool m_animating; + Timer<RenderProgress> m_animationTimer; +}; + +inline RenderProgress* toRenderProgress(RenderObject* object) +{ + ASSERT(!object || object->isProgress()); + return static_cast<RenderProgress*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderProgress(const RenderProgress*); + +} // namespace WebCore + +#endif + +#endif // RenderProgress_h + diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index ba579df..0ba99f5 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -109,7 +109,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty) } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) - paintOutline(paintInfo.context, tx, ty, width(), height(), style()); + paintOutline(paintInfo.context, tx, ty, width(), height()); if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h index bcf565d..b5c6179 100644 --- a/WebCore/rendering/RenderReplaced.h +++ b/WebCore/rendering/RenderReplaced.h @@ -48,7 +48,6 @@ protected: virtual void paint(PaintInfo&, int tx, int ty); bool shouldPaint(PaintInfo&, int& tx, int& ty); - void adjustOverflowForBoxShadowAndReflect(); IntRect localSelectionRect(bool checkWhetherSelected = true) const; private: diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp index 6d1b965..56846a9 100644 --- a/WebCore/rendering/RenderSVGContainer.cpp +++ b/WebCore/rendering/RenderSVGContainer.cpp @@ -27,9 +27,9 @@ #include "RenderSVGContainer.h" #include "GraphicsContext.h" +#include "RenderSVGResourceFilter.h" #include "RenderView.h" #include "SVGRenderSupport.h" -#include "SVGResourceFilter.h" #include "SVGStyledElement.h" namespace WebCore { @@ -70,7 +70,7 @@ bool RenderSVGContainer::selfWillPaint() const { #if ENABLE(FILTERS) const SVGRenderStyle* svgStyle = style()->svgStyle(); - SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter(), this); + RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), svgStyle->filterResource()); if (filter) return true; #endif @@ -95,7 +95,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) applyTransformToPaintInfo(childPaintInfo, localToParentTransform()); - SVGResourceFilter* filter = 0; + RenderSVGResourceFilter* filter = 0; FloatRect boundingBox = repaintRectInLocalCoordinates(); bool continueRendering = true; @@ -120,7 +120,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) // We should instead disable our clip during PaintPhaseOutline IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) - paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height(), style()); + paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height()); } // addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 6fb9501..1fb7c0f 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -42,6 +42,7 @@ namespace WebCore { RenderSVGImage::RenderSVGImage(SVGImageElement* impl) : RenderImage(impl) + , m_needsTransformUpdate(true) { } @@ -50,10 +51,13 @@ void RenderSVGImage::layout() ASSERT(needsLayout()); LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - SVGImageElement* image = static_cast<SVGImageElement*>(node()); - m_localTransform = image->animatedLocalTransform(); - + + if (m_needsTransformUpdate) { + m_localTransform = image->animatedLocalTransform(); + m_needsTransformUpdate = false; + } + // minimum height setHeight(errorOccurred() ? intrinsicSize().height() : 0); @@ -77,7 +81,7 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) paintInfo.context->concatCTM(localToParentTransform()); if (paintInfo.phase == PaintPhaseForeground) { - SVGResourceFilter* filter = 0; + RenderSVGResourceFilter* filter = 0; PaintInfo savedInfo(paintInfo); @@ -95,14 +99,14 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) - paintOutline(paintInfo.context, 0, 0, width(), height(), style()); + paintOutline(paintInfo.context, 0, 0, width(), height()); paintInfo.context->restore(); } void RenderSVGImage::destroy() { - SVGRenderBase::deregisterFromResources(this); + deregisterFromResources(this); RenderImage::destroy(); } diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index f48b9dd..120ac72 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -38,6 +38,8 @@ class RenderSVGImage : public RenderImage, protected SVGRenderBase { public: RenderSVGImage(SVGImageElement*); + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + private: virtual const SVGRenderBase* toSVGRenderBase() const { return this; } virtual const char* renderName() const { return "RenderSVGImage"; } @@ -72,6 +74,7 @@ private: virtual AffineTransform localTransform() const { return m_localTransform; } + bool m_needsTransformUpdate : 1; AffineTransform m_localTransform; FloatRect m_localBounds; mutable FloatRect m_cachedLocalRepaintRect; diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp index cf97b52..33459ce 100644 --- a/WebCore/rendering/RenderSVGInline.cpp +++ b/WebCore/rendering/RenderSVGInline.cpp @@ -48,9 +48,9 @@ InlineFlowBox* RenderSVGInline::createInlineFlowBox() void RenderSVGInline::absoluteRects(Vector<IntRect>& rects, int, int) { - InlineRunBox* firstBox = firstLineBox(); + InlineFlowBox* firstBox = firstLineBox(); - SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; + RootInlineBox* rootBox = firstBox ? firstBox->root() : 0; RenderBox* object = rootBox ? rootBox->block() : 0; if (!object) @@ -59,17 +59,45 @@ void RenderSVGInline::absoluteRects(Vector<IntRect>& rects, int, int) int xRef = object->x(); int yRef = object->y(); - for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { + for (InlineFlowBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->x(), yRef + curr->y(), curr->width(), curr->height()); rects.append(enclosingIntRect(localToAbsoluteQuad(rect).boundingBox())); } } +FloatRect RenderSVGInline::objectBoundingBox() const +{ + if (const RenderObject* object = findTextRootObject(this)) + return object->objectBoundingBox(); + + return FloatRect(); +} + +FloatRect RenderSVGInline::strokeBoundingBox() const +{ + const RenderObject* object = findTextRootObject(this); + ASSERT(object); + + const SVGRenderBase* renderer = object->toSVGRenderBase(); + if (!renderer) + return FloatRect(); + + return renderer->strokeBoundingBox(); +} + +FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const +{ + if (const RenderObject* object = findTextRootObject(this)) + return object->repaintRectInLocalCoordinates(); + + return FloatRect(); +} + void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads) { - InlineRunBox* firstBox = firstLineBox(); + InlineFlowBox* firstBox = firstLineBox(); - SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; + RootInlineBox* rootBox = firstBox ? firstBox->root() : 0; RenderBox* object = rootBox ? rootBox->block() : 0; if (!object) @@ -78,7 +106,7 @@ void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads) int xRef = object->x(); int yRef = object->y(); - for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { + for (InlineFlowBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->x(), yRef + curr->y(), curr->width(), curr->height()); quads.append(localToAbsoluteQuad(rect)); } diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h index 53fd4b7..e57b936 100644 --- a/WebCore/rendering/RenderSVGInline.h +++ b/WebCore/rendering/RenderSVGInline.h @@ -31,9 +31,12 @@ namespace WebCore { -class RenderSVGInline : public RenderInline { +class RenderSVGInline : public RenderInline, protected SVGRenderBase { public: RenderSVGInline(Node*); + + virtual const SVGRenderBase* toSVGRenderBase() const { return this; } + virtual const char* renderName() const { return "RenderSVGInline"; } virtual bool requiresLayer() const { return false; } @@ -41,8 +44,14 @@ public: virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); - virtual FloatRect objectBoundingBox() const { return FloatRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } + // Chapter 10.4 of the SVG Specification say that we should use the + // object bounding box of the parent text element. + // We search for the root text element and take it's bounding box. + // It is also necessary to take the stroke and repaint rect of + // this element, since we need it for filters. + virtual FloatRect objectBoundingBox() const; + virtual FloatRect strokeBoundingBox() const; + virtual FloatRect repaintRectInLocalCoordinates() const; private: virtual InlineFlowBox* createInlineFlowBox(); diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp index c163dc6..837b36a 100644 --- a/WebCore/rendering/RenderSVGModelObject.cpp +++ b/WebCore/rendering/RenderSVGModelObject.cpp @@ -63,7 +63,7 @@ void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintCont // Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content. // FIXME: This may also need to move into SVGRenderBase as the RenderBox version depends // on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement. -IntRect RenderSVGModelObject::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const +IntRect RenderSVGModelObject::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, IntPoint*) const { IntRect box = enclosingIntRect(repaintRectInLocalCoordinates()); adjustRectForOutlineAndShadow(box); diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index c04c590..760e79a 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -55,7 +55,7 @@ public: virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); - virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const; + virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, IntPoint*) const; virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 38c6c09..1665404 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -28,12 +28,58 @@ namespace WebCore { enum RenderSVGResourceType { - MaskerResourceType + MaskerResourceType, + MarkerResourceType, + FilterResourceType, + ClipperResourceType }; class RenderSVGResource : public RenderSVGHiddenContainer { public: - RenderSVGResource(SVGStyledElement* node) : RenderSVGHiddenContainer(node) { } + RenderSVGResource(SVGStyledElement* node) + : RenderSVGHiddenContainer(node) + , m_id(node->getIDAttribute()) + { + ASSERT(node->document()); + node->document()->accessSVGExtensions()->addResource(m_id, this); + } + + virtual ~RenderSVGResource() + { + ASSERT(node()); + ASSERT(node()->document()); + node()->document()->accessSVGExtensions()->removeResource(m_id); + } + + void idChanged() + { + ASSERT(node()); + ASSERT(node()->document()); + SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); + + // Remove old id, that is guaranteed to be present in cache + extensions->removeResource(m_id); + + m_id = static_cast<Element*>(node())->getIDAttribute(); + + // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now + if (extensions->isPendingResource(m_id)) { + OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); + if (clients->isEmpty()) + return; + + HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); + const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + + for (; it != end; ++it) { + if (RenderObject* renderer = (*it)->renderer()) + renderer->setNeedsLayout(true); + } + } + + // Recache us with the new id + extensions->addResource(m_id, this); + } template<class Renderer> Renderer* cast() @@ -51,10 +97,14 @@ public: virtual void invalidateClients() = 0; virtual void invalidateClient(RenderObject*) = 0; - virtual bool applyResource(RenderObject*, GraphicsContext*) = 0; + virtual bool applyResource(RenderObject*, GraphicsContext*&) = 0; + virtual void postApplyResource(RenderObject*, GraphicsContext*&) { } virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0; virtual RenderSVGResourceType resourceType() const = 0; + +private: + AtomicString m_id; }; template<typename Renderer> @@ -63,19 +113,10 @@ Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id) if (id.isEmpty()) return 0; - Element* element = document->getElementById(id); - if (!element || !element->isSVGElement()) - return 0; - - RenderObject* renderer = element->renderer(); - if (!renderer) - return 0; - - RenderSVGResource* renderResource = renderer->toRenderSVGResource(); - if (!renderResource) - return 0; + if (RenderSVGResource* renderResource = document->accessSVGExtensions()->resourceById(id)) + return renderResource->cast<Renderer>(); - return renderResource->cast<Renderer>(); + return 0; } } diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp new file mode 100644 index 0000000..ccb7397 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org> + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderSVGResourceClipper.h" + +#include "AffineTransform.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "IntRect.h" +#include "RenderObject.h" +#include "RenderStyle.h" +#include "RenderSVGResource.h" +#include "SVGClipPathElement.h" +#include "SVGElement.h" +#include "SVGRenderSupport.h" +#include "SVGStyledElement.h" +#include "SVGStyledTransformableElement.h" +#include "SVGUnitTypes.h" +#include "SVGUseElement.h" + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType; + +RenderSVGResourceClipper::RenderSVGResourceClipper(SVGStyledElement* node) + : RenderSVGResource(node) +{ +} + +RenderSVGResourceClipper::~RenderSVGResourceClipper() +{ + deleteAllValues(m_clipper); + m_clipper.clear(); +} + +void RenderSVGResourceClipper::invalidateClients() +{ + HashMap<RenderObject*, ClipperData*>::const_iterator end = m_clipper.end(); + for (HashMap<RenderObject*, ClipperData*>::const_iterator it = m_clipper.begin(); it != end; ++it) { + RenderObject* renderer = it->first; + renderer->setNeedsBoundariesUpdate(); + renderer->setNeedsLayout(true); + } + deleteAllValues(m_clipper); + m_clipper.clear(); +} + +void RenderSVGResourceClipper::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashSet should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_clipper.contains(object)) + return; + + delete m_clipper.take(object); +} + +bool RenderSVGResourceClipper::applyResource(RenderObject* object, GraphicsContext*& context) +{ + applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context); + return true; +} + +bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const FloatRect& objectBoundingBox) +{ + // If the current clip-path gets clipped itself, we have to fallback to masking. + if (!style()->svgStyle()->clipperResource().isEmpty()) + return false; + WindRule clipRule = RULE_NONZERO; + Path clipPath = Path(); + + // If clip-path only contains one visible shape or path, we can use path-based clipping. Invisible + // shapes don't affect the clipping and can be ignored. If clip-path contains more than one + // visible shape, the additive clipping may not work, caused by the clipRule. EvenOdd + // as well as NonZero can cause self-clipping of the elements. + // See also http://www.w3.org/TR/SVG/painting.html#FillRuleProperty + for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { + RenderObject* renderer = childNode->renderer(); + if (!renderer) + continue; + // Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts. + if (renderer->isSVGText()) + return false; + if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyledTransformable()) + continue; + SVGStyledTransformableElement* styled = static_cast<SVGStyledTransformableElement*>(childNode); + RenderStyle* style = renderer->style(); + if (!style || style->display() == NONE || style->visibility() != VISIBLE) + continue; + const SVGRenderStyle* svgStyle = style->svgStyle(); + // Current shape in clip-path gets clipped too. Fallback to masking. + if (!svgStyle->clipperResource().isEmpty()) + return false; + // Fallback to masking, if there is more than one clipping path. + if (clipPath.isEmpty()) { + clipPath = styled->toClipPath(); + clipRule = svgStyle->clipRule(); + } else + return false; + } + // Only one visible shape/path was found. Directly continue clipping and transform the content to userspace if necessary. + if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + AffineTransform transform; + transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + clipPath.transform(transform); + } + // The SVG specification wants us to clip everything, if clip-path doesn't have a child. + if (clipPath.isEmpty()) + clipPath.addRect(FloatRect()); + context->beginPath(); + context->addPath(clipPath); + context->clipPath(clipRule); + return true; +} + +bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox, + const FloatRect& repaintRect, GraphicsContext* context) +{ + ASSERT(object); + ASSERT(context); + + if (!m_clipper.contains(object)) + m_clipper.set(object, new ClipperData); + + ClipperData* clipperData = m_clipper.get(object); + if (!clipperData->clipMaskImage) { + if (pathOnlyClipping(context, objectBoundingBox)) + return true; + createClipData(clipperData, objectBoundingBox, repaintRect); + } + + if (!clipperData->clipMaskImage) + return false; + + context->clipToImageBuffer(repaintRect, clipperData->clipMaskImage.get()); + return true; +} + +bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const FloatRect& objectBoundingBox, const FloatRect& repaintRect) +{ + IntRect clipMaskRect = enclosingIntRect(repaintRect); + clipperData->clipMaskImage = ImageBuffer::create(clipMaskRect.size()); + if (!clipperData->clipMaskImage) + return false; + + GraphicsContext* maskContext = clipperData->clipMaskImage->context(); + ASSERT(maskContext); + + maskContext->save(); + maskContext->translate(-repaintRect.x(), -repaintRect.y()); + + // clipPath can also be clipped by another clipPath. + bool clipperGetsClipped = false; + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(this->document(), style()->svgStyle()->clipperResource())) { + clipperGetsClipped = true; + if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) { + maskContext->restore(); + return false; + } + } + + SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node()); + if (clipPath->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + maskContext->translate(objectBoundingBox.x(), objectBoundingBox.y()); + maskContext->scale(objectBoundingBox.size()); + } + + // Draw all clipPath children into a global mask. + for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { + RenderObject* renderer = childNode->renderer(); + if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + continue; + RenderStyle* style = renderer->style(); + if (!style || style->display() == NONE || style->visibility() != VISIBLE) + continue; + + WindRule newClipRule = style->svgStyle()->clipRule(); + bool isUseElement = renderer->isSVGShadowTreeRootContainer(); + if (isUseElement) { + SVGUseElement* useElement = static_cast<SVGUseElement*>(childNode); + renderer = useElement->rendererClipChild(); + if (!renderer) + continue; + if (!useElement->hasAttribute(SVGNames::clip_ruleAttr)) + newClipRule = renderer->style()->svgStyle()->clipRule(); + } + + // Only shapes, paths and texts are allowed for clipping. + if (!renderer->isRenderPath() && !renderer->isSVGText()) + continue; + + // Save the old RenderStyle of the current object for restoring after drawing + // it to the MaskImage. The new intermediate RenderStyle needs to inherit from + // the old one. + RefPtr<RenderStyle> oldRenderStyle = renderer->style(); + RefPtr<RenderStyle> newRenderStyle = RenderStyle::clone(oldRenderStyle.get()); + SVGRenderStyle* svgStyle = newRenderStyle.get()->accessSVGStyle(); + svgStyle->setFillPaint(SVGPaint::defaultFill()); + svgStyle->setStrokePaint(SVGPaint::defaultStroke()); + svgStyle->setFillRule(newClipRule); + newRenderStyle.get()->setOpacity(1.0f); + svgStyle->setFillOpacity(1.0f); + svgStyle->setStrokeOpacity(1.0f); + svgStyle->setFilterResource(String()); + svgStyle->setMaskerResource(String()); + renderer->setStyle(newRenderStyle.release()); + + // Get the renderer of the element, that is referenced by the <use>-element. + if (isUseElement) + renderer = childNode->renderer(); + + renderSubtreeToImage(clipperData->clipMaskImage.get(), renderer); + + renderer->setStyle(oldRenderStyle.release()); + } + + maskContext->restore(); + + return true; +} + +FloatRect RenderSVGResourceClipper::resourceBoundingBox(const FloatRect& objectBoundingBox) const +{ + // This is a rough heuristic to appraise the clip size and doesn't consider clip on clip. + FloatRect clipRect; + for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { + RenderObject* renderer = childNode->renderer(); + if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + continue; + if (!renderer->isRenderPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer()) + continue; + clipRect.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates())); + } + + if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + AffineTransform transform; + transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + return transform.mapRect(clipRect); + } + + return clipRect; +} + +} diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h new file mode 100644 index 0000000..8de17d4 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResourceClipper_h +#define RenderSVGResourceClipper_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "IntSize.h" +#include "Path.h" +#include "RenderSVGResource.h" +#include "SVGClipPathElement.h" +#include "SVGUnitTypes.h" + +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +struct ClipperData { + OwnPtr<ImageBuffer> clipMaskImage; +}; + +class RenderSVGResourceClipper : public RenderSVGResource { + +public: + RenderSVGResourceClipper(SVGStyledElement*); + virtual ~RenderSVGResourceClipper(); + + virtual const char* renderName() const { return "RenderSVGResourceClipper"; } + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, GraphicsContext*&); + virtual FloatRect resourceBoundingBox(const FloatRect&) const; + + virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; } + + SVGUnitTypes::SVGUnitType clipPathUnits() const { return toUnitType(static_cast<SVGClipPathElement*>(node())->clipPathUnits()); } + + static RenderSVGResourceType s_resourceType; +private: + // clipPath can be clipped too, but don't have a boundingBox or repaintRect. So we can't call + // applyResource directly and use the rects from the object, since they are empty for RenderSVGResources + bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*); + bool pathOnlyClipping(GraphicsContext*, const FloatRect&); + bool createClipData(ClipperData*, const FloatRect&, const FloatRect&); + + HashMap<RenderObject*, ClipperData*> m_clipper; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp new file mode 100644 index 0000000..cbedfe3 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * 2004, 2005 Rob Buis <buis@kde.org> + * 2005 Eric Seidel <eric@webkit.org> + * 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "RenderSVGResourceFilter.h" + +#include "AffineTransform.h" +#include "FloatPoint.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "ImageData.h" +#include "IntRect.h" +#include "RenderSVGResource.h" +#include "SVGElement.h" +#include "SVGFilter.h" +#include "SVGFilterElement.h" +#include "SVGFilterPrimitiveStandardAttributes.h" +#include "SVGStyledElement.h" +#include "SVGUnitTypes.h" +#include <wtf/Vector.h> + +static const float kMaxFilterSize = 5000.0f; + +using namespace std; + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType; + +RenderSVGResourceFilter::RenderSVGResourceFilter(SVGStyledElement* node) + : RenderSVGResource(node) + , m_savedContext(0) + , m_sourceGraphicBuffer(0) +{ +} + +RenderSVGResourceFilter::~RenderSVGResourceFilter() +{ + deleteAllValues(m_filter); + m_filter.clear(); +} + +void RenderSVGResourceFilter::invalidateClients() +{ + HashMap<RenderObject*, FilterData*>::const_iterator end = m_filter.end(); + for (HashMap<RenderObject*, FilterData*>::const_iterator it = m_filter.begin(); it != end; ++it) { + RenderObject* renderer = it->first; + renderer->setNeedsBoundariesUpdate(); + renderer->setNeedsLayout(true); + } + deleteAllValues(m_filter); + m_filter.clear(); +} + +void RenderSVGResourceFilter::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_filter.contains(object)) + return; + + delete m_filter.take(object); +} + +PassOwnPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() +{ + SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); + bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; + + // Add effects to the builder + OwnPtr<SVGFilterBuilder> builder(new SVGFilterBuilder); + builder->clearEffects(); + for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) { + if (!node->isSVGElement()) + continue; + + SVGElement* element = static_cast<SVGElement*>(node); + if (!element->isFilterEffect()) + continue; + + SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); + RefPtr<FilterEffect> effect = effectElement->build(builder.get()); + if (!effect) { + builder->clearEffects(); + return 0; + } + effectElement->setStandardAttributes(primitiveBoundingBoxMode, effect.get()); + builder->add(effectElement->result(), effect); + } + return builder.release(); +} + +bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale) +{ + bool matchesFilterSize = true; + if (size.width() > kMaxFilterSize) { + scale.setWidth(scale.width() * kMaxFilterSize / size.width()); + matchesFilterSize = false; + } + if (size.height() > kMaxFilterSize) { + scale.setHeight(scale.height() * kMaxFilterSize / size.height()); + matchesFilterSize = false; + } + + return matchesFilterSize; +} + +bool RenderSVGResourceFilter::applyResource(RenderObject* object, GraphicsContext*& context) +{ + ASSERT(object); + ASSERT(context); + + // Returning false here, to avoid drawings onto the context. We just want to + // draw the stored filter output, not the unfiltered object as well. + if (m_filter.contains(object)) { + FilterData* filterData = m_filter.get(object); + if (filterData->builded) + return false; + + delete m_filter.take(object); // Oops, have to rebuild, go through normal code path + } + + OwnPtr<FilterData> filterData(new FilterData); + filterData->builder = buildPrimitives(); + if (!filterData->builder) + return false; + + const SVGRenderBase* renderer = object->toSVGRenderBase(); + if (!renderer) + return false; + + FloatRect paintRect = renderer->strokeBoundingBox(); + paintRect.unite(renderer->markerBoundingBox()); + + // Calculate the scale factor for the use of filterRes. + // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion + SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); + filterData->boundaries = filterElement->filterBoundingBox(object->objectBoundingBox()); + if (filterData->boundaries.isEmpty()) + return false; + + FloatSize scale(1.0f, 1.0f); + if (filterElement->hasAttribute(SVGNames::filterResAttr)) { + scale.setWidth(filterElement->filterResX() / filterData->boundaries.width()); + scale.setHeight(filterElement->filterResY() / filterData->boundaries.height()); + } + + if (scale.isEmpty()) + return false; + + // clip sourceImage to filterRegion + FloatRect clippedSourceRect = paintRect; + clippedSourceRect.intersect(filterData->boundaries); + + // scale filter size to filterRes + FloatRect tempSourceRect = clippedSourceRect; + + // scale to big sourceImage size to kMaxFilterSize + tempSourceRect.scale(scale.width(), scale.height()); + fitsInMaximumImageSize(tempSourceRect.size(), scale); + + // prepare Filters + bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; + filterData->filter = SVGFilter::create(paintRect, filterData->boundaries, primitiveBoundingBoxMode); + filterData->filter->setFilterResolution(scale); + + FilterEffect* lastEffect = filterData->builder->lastEffect(); + if (!lastEffect) + return false; + + lastEffect->calculateEffectRect(filterData->filter.get()); + // At least one FilterEffect has a too big image size, + // recalculate the effect sizes with new scale factors. + if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) { + filterData->filter->setFilterResolution(scale); + lastEffect->calculateEffectRect(filterData->filter.get()); + } + + clippedSourceRect.scale(scale.width(), scale.height()); + + // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. + // The size of the SourceGraphic is clipped to the size of the filterRegion. + IntRect bufferRect = enclosingIntRect(clippedSourceRect); + OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB)); + + if (!sourceGraphic.get()) + return false; + + GraphicsContext* sourceGraphicContext = sourceGraphic->context(); + sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y()); + sourceGraphicContext->scale(scale); + sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size())); + m_sourceGraphicBuffer.set(sourceGraphic.release()); + m_savedContext = context; + + context = sourceGraphicContext; + m_filter.set(object, filterData.release()); + + return true; +} + +void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context) +{ + ASSERT(object); + ASSERT(context); + + if (!m_filter.contains(object)) + return; + + FilterData* filterData = m_filter.get(object); + if (!filterData->builded) { + if (!m_savedContext) { + invalidateClient(object); + return; + } + + context = m_savedContext; + m_savedContext = 0; +#if !PLATFORM(CG) + m_sourceGraphicBuffer->transformColorSpace(DeviceRGB, LinearRGB); +#endif + } + + FilterEffect* lastEffect = filterData->builder->lastEffect(); + + if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->subRegion().isEmpty()) { + // This is the real filtering of the object. It just needs to be called on the + // initial filtering process. We just take the stored filter result on a + // second drawing. + if (!filterData->builded) { + filterData->filter->setSourceImage(m_sourceGraphicBuffer.release()); + lastEffect->apply(filterData->filter.get()); + filterData->builded = true; + } + + ImageBuffer* resultImage = lastEffect->resultImage(); + if (resultImage) { +#if !PLATFORM(CG) + resultImage->transformColorSpace(LinearRGB, DeviceRGB); +#endif + context->drawImage(resultImage->image(), object->style()->colorSpace(), lastEffect->subRegion()); + } + } + + m_sourceGraphicBuffer.clear(); +} + +FloatRect RenderSVGResourceFilter::resourceBoundingBox(const FloatRect& objectBoundingBox) const +{ + if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node())) + return element->filterBoundingBox(objectBoundingBox); + + return FloatRect(); +} + +} +#endif diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h new file mode 100644 index 0000000..2cd4b6c --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * 2004, 2005 Rob Buis <buis@kde.org> + * 2005 Eric Seidel <eric@webkit.org> + * 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResourceFilter_h +#define RenderSVGResourceFilter_h + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "FloatRect.h" +#include "ImageBuffer.h" +#include "RenderSVGResource.h" +#include "SVGFilter.h" +#include "SVGFilterBuilder.h" +#include "SVGFilterElement.h" +#include "SVGUnitTypes.h" + +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +struct FilterData { + FilterData() + : builded(false) + { + } + + RefPtr<SVGFilter> filter; + OwnPtr<SVGFilterBuilder> builder; + FloatRect boundaries; + FloatSize scale; + bool builded; +}; + +class GraphicsContext; + +class RenderSVGResourceFilter : public RenderSVGResource { +public: + RenderSVGResourceFilter(SVGStyledElement*); + virtual ~RenderSVGResourceFilter(); + + virtual const char* renderName() const { return "RenderSVGResourceFilter"; } + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, GraphicsContext*&); + virtual void postApplyResource(RenderObject*, GraphicsContext*&); + + virtual FloatRect resourceBoundingBox(const FloatRect&) const; + + PassOwnPtr<SVGFilterBuilder> buildPrimitives(); + + SVGUnitTypes::SVGUnitType filterUnits() const { return toUnitType(static_cast<SVGFilterElement*>(node())->filterUnits()); } + SVGUnitTypes::SVGUnitType primitiveUnits() const { return toUnitType(static_cast<SVGFilterElement*>(node())->primitiveUnits()); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + +private: + bool fitsInMaximumImageSize(const FloatSize&, FloatSize&); + + // Intermediate storage during + GraphicsContext* m_savedContext; + OwnPtr<ImageBuffer> m_sourceGraphicBuffer; + + HashMap<RenderObject*, FilterData*> m_filter; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp new file mode 100644 index 0000000..c526962 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMarker.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org> + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderSVGResourceMarker.h" + +#include "GraphicsContext.h" +#include "RenderSVGContainer.h" +#include "SVGElement.h" +#include "SVGMarkerElement.h" +#include "SVGRenderSupport.h" +#include "SVGStyledElement.h" +#include "SVGStyledTransformableElement.h" + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType; + +RenderSVGResourceMarker::RenderSVGResourceMarker(SVGStyledElement* node) + : RenderSVGResource(node) +{ +} + +RenderSVGResourceMarker::~RenderSVGResourceMarker() +{ + m_marker.clear(); +} + +void RenderSVGResourceMarker::layout() +{ + // RenderSVGHiddenContainer overwrites layout(). We need the + // layouting of RenderSVGContainer for calculating local + // transformations and repaint. + RenderSVGContainer::layout(); +} + +void RenderSVGResourceMarker::addClient(const RenderObject* object) +{ + m_marker.add(object); +} + +void RenderSVGResourceMarker::invalidateClients() +{ + const HashSet<const RenderObject*>::const_iterator end = m_marker.end(); + for (HashSet<const RenderObject*>::const_iterator it = m_marker.begin(); it != end; ++it) { + RenderObject* renderer = const_cast<RenderObject*>(*it); + renderer->setNeedsBoundariesUpdate(); + renderer->setNeedsLayout(true); + } + + m_marker.clear(); +} + +void RenderSVGResourceMarker::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashSet should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_marker.contains(object)) + return; + + m_marker.remove(object); +} + +void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo) +{ + if (SVGRenderBase::isOverflowHidden(this)) + paintInfo.context->clip(m_viewport); +} + +FloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const +{ + FloatRect coordinates = RenderSVGContainer::repaintRectInLocalCoordinates(); + + // Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated + coordinates = localToParentTransform().mapRect(coordinates); + + return markerTransformation.mapRect(coordinates); +} + +const AffineTransform& RenderSVGResourceMarker::localToParentTransform() const +{ + AffineTransform viewportTranslation(viewportTransform()); + m_localToParentTransform = viewportTranslation.translateRight(m_viewport.x(), m_viewport.y()); + return m_localToParentTransform; + // If this class were ever given a localTransform(), then the above would read: + // return viewportTransform() * localTransform() * viewportTranslation; +} + +FloatPoint RenderSVGResourceMarker::referencePoint() const +{ + SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + ASSERT(marker); + + return FloatPoint(marker->refX().value(marker), marker->refY().value(marker)); +} + +float RenderSVGResourceMarker::angle() const +{ + SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + ASSERT(marker); + + float angle = -1; + if (marker->orientType() == SVGMarkerElement::SVG_MARKER_ORIENT_ANGLE) + angle = marker->orientAngle().value(); + + return angle; +} + +AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& origin, float autoAngle, float strokeWidth) const +{ + SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + ASSERT(marker); + + float markerAngle = angle(); + bool useStrokeWidth = (marker->markerUnits() == SVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH); + + AffineTransform transform; + transform.translate(origin.x(), origin.y()); + transform.rotate(markerAngle == -1 ? autoAngle : markerAngle); + transform = markerContentTransformation(transform, referencePoint(), useStrokeWidth ? strokeWidth : -1); + return transform; +} + +void RenderSVGResourceMarker::draw(RenderObject::PaintInfo& paintInfo, const AffineTransform& transform) +{ + DEFINE_STATIC_LOCAL(HashSet<RenderSVGResourceMarker*>, currentlyDrawingMarkers, ()); + + // avoid drawing circular marker references + if (currentlyDrawingMarkers.contains(this)) + return; + + currentlyDrawingMarkers.add(this); + RenderObject::PaintInfo info(paintInfo); + info.context->save(); + applyTransformToPaintInfo(info, transform); + RenderSVGContainer::paint(info, 0, 0); + info.context->restore(); + + currentlyDrawingMarkers.remove(this); +} + +AffineTransform RenderSVGResourceMarker::markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth) const +{ + // The 'origin' coordinate maps to SVGs refX/refY, given in coordinates relative to the viewport established by the marker + FloatPoint mappedOrigin = viewportTransform().mapPoint(origin); + + AffineTransform transformation = contentTransformation; + if (strokeWidth != -1) + transformation.scaleNonUniform(strokeWidth, strokeWidth); + + transformation.translate(-mappedOrigin.x(), -mappedOrigin.y()); + return transformation; +} + +AffineTransform RenderSVGResourceMarker::viewportTransform() const +{ + SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + ASSERT(marker); + + return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); +} + +void RenderSVGResourceMarker::calcViewport() +{ + if (!selfNeedsLayout()) + return; + + SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + ASSERT(marker); + + float w = marker->markerWidth().value(marker); + float h = marker->markerHeight().value(marker); + m_viewport = FloatRect(0, 0, w, h); +} + +} diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h new file mode 100644 index 0000000..9e39b99 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMarker.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResourceMarker_h +#define RenderSVGResourceMarker_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "RenderObject.h" +#include "RenderSVGResource.h" +#include "SVGMarkerElement.h" +#include "SVGStyledElement.h" + +#include <wtf/HashSet.h> + +namespace WebCore { + +class AffineTransform; + +class RenderSVGResourceMarker : public RenderSVGResource { + +public: + RenderSVGResourceMarker(SVGStyledElement*); + virtual ~RenderSVGResourceMarker(); + + virtual const char* renderName() const { return "RenderSVGResourceMarker"; } + + void addClient(const RenderObject*); + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + void draw(RenderObject::PaintInfo&, const AffineTransform&); + + // Calculates marker boundaries, mapped to the target element's coordinate space + FloatRect markerBoundaries(const AffineTransform& markerTransformation) const; + + virtual void applyViewportClip(PaintInfo&); + virtual void layout(); + virtual void calcViewport(); + + virtual const AffineTransform& localToParentTransform() const; + AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const; + + virtual bool applyResource(RenderObject*, GraphicsContext*&) { return false; } + virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); } + + FloatPoint referencePoint() const; + float angle() const; + SVGMarkerElement::SVGMarkerUnitsType markerUnits() const { return static_cast<SVGMarkerElement::SVGMarkerUnitsType>(static_cast<SVGMarkerElement*>(node())->markerUnits()); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + +private: + // Generates a transformation matrix usable to render marker content. Handles scaling the marker content + // acording to SVGs markerUnits="strokeWidth" concept, when a strokeWidth value != -1 is passed in. + AffineTransform markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth = -1) const; + + AffineTransform viewportTransform() const; + + // Save objects using this marker for invalidation. + HashSet<const RenderObject*> m_marker; + + mutable AffineTransform m_localToParentTransform; + FloatRect m_viewport; +}; + +} +#endif + +#endif diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 2923c6e..8bb16de 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -31,6 +31,7 @@ #include "ImageBuffer.h" #include "ImageData.h" #include "IntRect.h" +#include "RenderSVGResource.h" #include "SVGElement.h" #include "SVGMaskElement.h" #include "SVGStyledElement.h" @@ -55,8 +56,12 @@ RenderSVGResourceMasker::~RenderSVGResourceMasker() void RenderSVGResourceMasker::invalidateClients() { HashMap<RenderObject*, MaskerData*>::const_iterator end = m_masker.end(); - for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) - it->first->setNeedsLayout(true); + for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) { + RenderObject* renderer = it->first; + renderer->setNeedsBoundariesUpdate(); + renderer->setNeedsLayout(true); + } + deleteAllValues(m_masker); m_masker.clear(); } @@ -75,7 +80,7 @@ void RenderSVGResourceMasker::invalidateClient(RenderObject* object) delete m_masker.take(object); } -bool RenderSVGResourceMasker::applyResource(RenderObject* object, GraphicsContext* context) +bool RenderSVGResourceMasker::applyResource(RenderObject* object, GraphicsContext*& context) { ASSERT(object); ASSERT(context); diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index 6c73c84..3127e3c 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -58,7 +58,7 @@ public: virtual void invalidateClients(); virtual void invalidateClient(RenderObject*); - virtual bool applyResource(RenderObject*, GraphicsContext*); + virtual bool applyResource(RenderObject*, GraphicsContext*&); virtual FloatRect resourceBoundingBox(const FloatRect&) const; SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); } diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 51bf3e7..5ed0871 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -35,7 +35,7 @@ #include "TransformState.h" #if ENABLE(FILTERS) -#include "SVGResourceFilter.h" +#include "RenderSVGResourceFilter.h" #endif using namespace std; @@ -129,7 +129,7 @@ bool RenderSVGRoot::selfWillPaint() const { #if ENABLE(FILTERS) const SVGRenderStyle* svgStyle = style()->svgStyle(); - SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter(), this); + RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document(), svgStyle->filterResource()); if (filter) return true; #endif @@ -166,7 +166,7 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) // Transform from our paint container's coordinate system to our local coords. applyTransformToPaintInfo(childPaintInfo, localToRepaintContainerTransform(parentOriginInContainer)); - SVGResourceFilter* filter = 0; + RenderSVGResourceFilter* filter = 0; FloatRect boundingBox = repaintRectInLocalCoordinates(); bool continueRendering = true; @@ -182,7 +182,7 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) childPaintInfo.context->restore(); if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) - paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style()); + paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height()); } void RenderSVGRoot::destroy() diff --git a/WebCore/rendering/RenderSVGShadowTreeRootContainer.h b/WebCore/rendering/RenderSVGShadowTreeRootContainer.h index 01cd427..81ae44b 100644 --- a/WebCore/rendering/RenderSVGShadowTreeRootContainer.h +++ b/WebCore/rendering/RenderSVGShadowTreeRootContainer.h @@ -33,6 +33,8 @@ public: RenderSVGShadowTreeRootContainer(SVGUseElement*); virtual ~RenderSVGShadowTreeRootContainer(); + virtual bool isSVGShadowTreeRootContainer() const { return true; } + void markShadowTreeForRecreation() { m_recreateTree = true; } void updateStyle(Node::StyleChange); virtual void updateFromElement(); diff --git a/WebCore/rendering/RenderSVGTSpan.h b/WebCore/rendering/RenderSVGTSpan.h index 652c5e3..931bd8c 100644 --- a/WebCore/rendering/RenderSVGTSpan.h +++ b/WebCore/rendering/RenderSVGTSpan.h @@ -31,12 +31,6 @@ class RenderSVGTSpan : public RenderSVGInline { public: RenderSVGTSpan(Node*); virtual const char* renderName() const { return "RenderSVGTSpan"; } - - // FIXME: These are incorrect, but have always behaved this way. - // These empty implementations prevent us from hitting RenderObject ASSERTS. - // tspan.getBBox() will be wrong, and repainting for tspans may not work correctly! - virtual FloatRect objectBoundingBox() const { return FloatRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } }; } diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index b8b9553..c0c4650 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -38,7 +38,6 @@ #include "RenderSVGRoot.h" #include "SVGLengthList.h" #include "SVGRenderSupport.h" -#include "SVGResourceFilter.h" #include "SVGRootInlineBox.h" #include "SVGTextElement.h" #include "SVGTransformList.h" @@ -49,6 +48,7 @@ namespace WebCore { RenderSVGText::RenderSVGText(SVGTextElement* node) : RenderSVGBlock(node) + , m_needsTransformUpdate(true) { } @@ -78,7 +78,10 @@ void RenderSVGText::layout() int yOffset = (int)(text->y()->getFirst().value(text)); setLocation(xOffset, yOffset); - m_localTransform = text->animatedLocalTransform(); + if (m_needsTransformUpdate) { + m_localTransform = text->animatedLocalTransform(); + m_needsTransformUpdate = false; + } RenderBlock::layout(); @@ -128,11 +131,8 @@ void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int) // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. - for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { - ASSERT(runBox->isInlineFlowBox()); - - InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); - for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { + for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { + for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each rect is very inefficient // we should compute the absoluteTransform outside this loop first. @@ -149,11 +149,8 @@ void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads) // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. - for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { - ASSERT(runBox->isInlineFlowBox()); - - InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); - for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { + for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { + for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each quad is very inefficient // we should compute the absoluteTransform outside this loop first. @@ -175,11 +172,8 @@ FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; - for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { - ASSERT(runBox->isInlineFlowBox()); - - InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); - for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) + for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { + for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index ab4b09b..fe53086 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -37,6 +37,8 @@ class RenderSVGText : public RenderSVGBlock { public: RenderSVGText(SVGTextElement* node); + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + private: virtual const char* renderName() const { return "RenderSVGText"; } @@ -67,11 +69,11 @@ private: virtual FloatRect strokeBoundingBox() const; virtual FloatRect repaintRectInLocalCoordinates() const; - // FIXME: This can be removed when localTransform() is removed from RenderObject virtual AffineTransform localTransform() const { return m_localTransform; } virtual RootInlineBox* createRootInlineBox(); + bool m_needsTransformUpdate : 1; AffineTransform m_localTransform; }; diff --git a/WebCore/rendering/RenderSVGTransformableContainer.cpp b/WebCore/rendering/RenderSVGTransformableContainer.cpp index 4bec7a7..94b9eea 100644 --- a/WebCore/rendering/RenderSVGTransformableContainer.cpp +++ b/WebCore/rendering/RenderSVGTransformableContainer.cpp @@ -31,29 +31,31 @@ namespace WebCore { RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransformableElement* node) : RenderSVGContainer(node) + , m_needsTransformUpdate(true) { } -const AffineTransform& RenderSVGTransformableContainer::localToParentTransform() const +void RenderSVGTransformableContainer::calculateLocalTransform() { - return m_localTransform; -} + SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); -AffineTransform RenderSVGTransformableContainer::localTransform() const -{ - return m_localTransform; -} + bool needsUpdate = m_needsTransformUpdate; + if (needsUpdate) { + m_localTransform = element->animatedLocalTransform(); + m_needsTransformUpdate = false; + } -void RenderSVGTransformableContainer::calculateLocalTransform() -{ - m_localTransform = static_cast<SVGStyledTransformableElement*>(node())->animatedLocalTransform(); - if (!node()->hasTagName(SVGNames::gTag) || !static_cast<SVGGElement*>(node())->isShadowTreeContainerElement()) + if (!element->hasTagName(SVGNames::gTag) || !static_cast<SVGGElement*>(element)->isShadowTreeContainerElement()) return; - FloatSize translation = static_cast<SVGShadowTreeContainerElement*>(node())->containerTranslation(); + FloatSize translation = static_cast<SVGShadowTreeContainerElement*>(element)->containerTranslation(); if (translation.width() == 0 && translation.height() == 0) return; + // FIXME: Could optimize this case for use to avoid refetching the animatedLocalTransform() here, if only the containerTranslation() changed. + if (!needsUpdate) + m_localTransform = element->animatedLocalTransform(); + m_localTransform.translate(translation.width(), translation.height()); } diff --git a/WebCore/rendering/RenderSVGTransformableContainer.h b/WebCore/rendering/RenderSVGTransformableContainer.h index 1de0b19..e6de054 100644 --- a/WebCore/rendering/RenderSVGTransformableContainer.h +++ b/WebCore/rendering/RenderSVGTransformableContainer.h @@ -31,13 +31,14 @@ namespace WebCore { public: RenderSVGTransformableContainer(SVGStyledTransformableElement*); - virtual const AffineTransform& localToParentTransform() const; + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } + virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: virtual void calculateLocalTransform(); - // FIXME: This can be made non-virtual once SVGRenderTreeAsText stops using localTransform() - virtual AffineTransform localTransform() const; + virtual AffineTransform localTransform() const { return m_localTransform; } + bool m_needsTransformUpdate : 1; AffineTransform m_localTransform; }; } diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp index 103d9d2..1587e7f 100644 --- a/WebCore/rendering/RenderSVGViewportContainer.cpp +++ b/WebCore/rendering/RenderSVGViewportContainer.cpp @@ -3,6 +3,7 @@ 2004, 2005, 2007 Rob Buis <buis@kde.org> 2007 Eric Seidel <eric@webkit.org> 2009 Google, Inc. + Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -26,9 +27,7 @@ #include "RenderSVGViewportContainer.h" #include "GraphicsContext.h" - #include "RenderView.h" -#include "SVGMarkerElement.h" #include "SVGSVGElement.h" namespace WebCore { @@ -38,29 +37,6 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node) { } -FloatRect RenderSVGViewportContainer::markerBoundaries(const AffineTransform& markerTransformation) const -{ - FloatRect coordinates = repaintRectInLocalCoordinates(); - - // Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated - coordinates = localToParentTransform().mapRect(coordinates); - - return markerTransformation.mapRect(coordinates); -} - -AffineTransform RenderSVGViewportContainer::markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth) const -{ - // The 'origin' coordinate maps to SVGs refX/refY, given in coordinates relative to the viewport established by the marker - FloatPoint mappedOrigin = viewportTransform().mapPoint(origin); - - AffineTransform transformation = contentTransformation; - if (strokeWidth != -1) - transformation.scaleNonUniform(strokeWidth, strokeWidth); - - transformation.translate(-mappedOrigin.x(), -mappedOrigin.y()); - return transformation; -} - void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo) { if (SVGRenderBase::isOverflowHidden(this)) @@ -81,14 +57,6 @@ void RenderSVGViewportContainer::calcViewport() float w = svg->width().value(svg); float h = svg->height().value(svg); m_viewport = FloatRect(x, y, w, h); - } else if (svgelem->hasTagName(SVGNames::markerTag)) { - if (!selfNeedsLayout()) - return; - - SVGMarkerElement* svg = static_cast<SVGMarkerElement*>(node()); - float w = svg->markerWidth().value(svg); - float h = svg->markerHeight().value(svg); - m_viewport = FloatRect(0, 0, w, h); } } @@ -97,9 +65,6 @@ AffineTransform RenderSVGViewportContainer::viewportTransform() const if (node()->hasTagName(SVGNames::svgTag)) { SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); - } else if (node()->hasTagName(SVGNames::markerTag)) { - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); - return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); } return AffineTransform(); diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h index c4043ec..7b5702b 100644 --- a/WebCore/rendering/RenderSVGViewportContainer.h +++ b/WebCore/rendering/RenderSVGViewportContainer.h @@ -34,13 +34,6 @@ class RenderSVGViewportContainer : public RenderSVGContainer { public: RenderSVGViewportContainer(SVGStyledElement*); - // Calculates marker boundaries, mapped to the target element's coordinate space - FloatRect markerBoundaries(const AffineTransform& markerTransformation) const; - - // Generates a transformation matrix usable to render marker content. Handles scaling the marker content - // acording to SVGs markerUnits="strokeWidth" concept, when a strokeWidth value != -1 is passed in. - AffineTransform markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth = -1) const; - private: virtual bool isSVGContainer() const { return true; } virtual const char* renderName() const { return "RenderSVGViewportContainer"; } diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 344f4ab..37b5e19 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -35,6 +35,7 @@ #include "RenderLayer.h" #include "RenderTheme.h" #include "RenderView.h" +#include "StepRange.h" #include <wtf/MathExtras.h> #ifdef ANDROID_LAYOUT @@ -49,80 +50,10 @@ using namespace HTMLNames; static const int defaultTrackLength = 129; -// FIXME: The SliderRange class and functions are entirely based on the DOM, -// and could be put with HTMLInputElement (possibly with a new name) instead of here. -struct SliderRange { - bool hasStep; - double step; - double minimum; - double maximum; // maximum must be >= minimum. - - explicit SliderRange(HTMLInputElement*); - double clampValue(double value); - - // Map value into 0-1 range - double proportionFromValue(double value) - { - if (minimum == maximum) - return 0; - - return (value - minimum) / (maximum - minimum); - } - - // Map from 0-1 range to value - double valueFromProportion(double proportion) - { - return minimum + proportion * (maximum - minimum); - } - - double valueFromElement(HTMLInputElement*, bool* wasClamped = 0); -}; - -SliderRange::SliderRange(HTMLInputElement* element) -{ - if (element->hasAttribute(precisionAttr)) { - step = 1.0; - hasStep = !equalIgnoringCase(element->getAttribute(precisionAttr), "float"); - } else - hasStep = element->getAllowedValueStep(&step); - - maximum = element->maximum(); - minimum = element->minimum(); -} - -double SliderRange::clampValue(double value) -{ - double clampedValue = max(minimum, min(value, maximum)); - if (!hasStep) - return clampedValue; - // Rounds clampedValue to minimum + N * step. - clampedValue = minimum + round((clampedValue - minimum) / step) * step; - if (clampedValue > maximum) - clampedValue -= step; - ASSERT(clampedValue >= minimum); - ASSERT(clampedValue <= maximum); - return clampedValue; -} - -double SliderRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) -{ - double oldValue; - bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(element->value(), &oldValue); - if (!parseSuccess) - oldValue = (minimum + maximum) / 2; - double newValue = clampValue(oldValue); - - if (wasClamped) - *wasClamped = !parseSuccess || newValue != oldValue; - - return newValue; -} - // Returns a value between 0 and 1. -// As with SliderRange, this could be on HTMLInputElement instead of here. static double sliderPosition(HTMLInputElement* element) { - SliderRange range(element); + StepRange range(element); return range.proportionFromValue(range.valueFromElement(element)); } @@ -376,15 +307,6 @@ void RenderSlider::layout() void RenderSlider::updateFromElement() { - HTMLInputElement* element = static_cast<HTMLInputElement*>(node()); - - // Send the value back to the element if the range changes it. - SliderRange range(element); - bool clamped; - double value = range.valueFromElement(element, &clamped); - if (clamped) - element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); - // Layout will take care of the thumb's size and position. if (!m_thumb) { m_thumb = new SliderThumbElement(document(), node()); @@ -434,7 +356,7 @@ void RenderSlider::setValueForPosition(int position) HTMLInputElement* element = static_cast<HTMLInputElement*>(node()); // Calculate the new value based on the position, and send it to the element. - SliderRange range(element); + StepRange range(element); double fraction = static_cast<double>(position) / trackSize(); if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 61e05ad..0a61a93 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -648,6 +648,25 @@ void RenderTable::appendColumn(int span) setNeedsLayoutAndPrefWidthsRecalc(); } +RenderTableCol* RenderTable::nextColElement(RenderTableCol* current) const +{ + RenderObject* next = current->firstChild(); + if (!next) + next = current->nextSibling(); + if (!next && current->parent()->isTableCol()) + next = current->parent()->nextSibling(); + + while (next) { + if (next->isTableCol()) + return toRenderTableCol(next); + if (next != m_caption) + return 0; + next = next->nextSibling(); + } + + return 0; +} + RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const { if (!m_hasColElements) @@ -656,32 +675,31 @@ RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) int cCol = 0; while (child) { - if (child->isTableCol()) { - RenderTableCol* colElem = toRenderTableCol(child); - int span = colElem->span(); - if (!colElem->firstChild()) { - int startCol = cCol; - int endCol = cCol + span - 1; - cCol += span; - if (cCol > col) { - if (startEdge) - *startEdge = startCol == col; - if (endEdge) - *endEdge = endCol == col; - return colElem; - } - } - - RenderObject* next = child->firstChild(); - if (!next) - next = child->nextSibling(); - if (!next && child->parent()->isTableCol()) - next = child->parent()->nextSibling(); - child = next; - } else if (child == m_caption) - child = child->nextSibling(); - else + if (child->isTableCol()) break; + if (child != m_caption) + return 0; + child = child->nextSibling(); + } + if (!child) + return 0; + + RenderTableCol* colElem = toRenderTableCol(child); + while (colElem) { + int span = colElem->span(); + if (!colElem->firstChild()) { + int startCol = cCol; + int endCol = cCol + span - 1; + cCol += span; + if (cCol > col) { + if (startEdge) + *startEdge = startCol == col; + if (endEdge) + *endEdge = endCol == col; + return colElem; + } + } + colElem = nextColElement(colElem); } return 0; @@ -773,7 +791,7 @@ int RenderTable::calcBorderLeft() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = tb.width; + borderWidth = tb.width(); int leftmostColumn = style()->direction() == RTL ? numEffCols() - 1 : 0; RenderTableCol* colGroup = colElement(leftmostColumn); @@ -782,7 +800,7 @@ int RenderTable::calcBorderLeft() const if (gb.style() == BHIDDEN) return 0; if (gb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(gb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(gb.width())); } RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot); @@ -795,7 +813,7 @@ int RenderTable::calcBorderLeft() const return 0; if (sb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(sb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(sb.width())); const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, leftmostColumn); @@ -809,9 +827,9 @@ int RenderTable::calcBorderLeft() const return 0; if (cb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(cb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(cb.width())); if (rb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(rb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(rb.width())); } } return borderWidth / 2; @@ -832,7 +850,7 @@ int RenderTable::calcBorderRight() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = tb.width; + borderWidth = tb.width(); int rightmostColumn = style()->direction() == RTL ? 0 : numEffCols() - 1; RenderTableCol* colGroup = colElement(rightmostColumn); @@ -841,7 +859,7 @@ int RenderTable::calcBorderRight() const if (gb.style() == BHIDDEN) return 0; if (gb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(gb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(gb.width())); } RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot); @@ -854,7 +872,7 @@ int RenderTable::calcBorderRight() const return 0; if (sb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(sb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(sb.width())); const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, rightmostColumn); @@ -868,9 +886,9 @@ int RenderTable::calcBorderRight() const return 0; if (cb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(cb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(cb.width())); if (rb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<unsigned>(rb.width)); + borderWidth = max(borderWidth, static_cast<unsigned>(rb.width())); } } return (borderWidth + 1) / 2; @@ -921,7 +939,7 @@ int RenderTable::outerBorderTop() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<int>(tb.width / 2)); + borderWidth = max(borderWidth, static_cast<int>(tb.width() / 2)); return borderWidth; } @@ -947,7 +965,7 @@ int RenderTable::outerBorderBottom() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = max(borderWidth, static_cast<int>((tb.width + 1) / 2)); + borderWidth = max(borderWidth, static_cast<int>((tb.width() + 1) / 2)); return borderWidth; } @@ -962,7 +980,7 @@ int RenderTable::outerBorderLeft() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = tb.width / 2; + borderWidth = tb.width() / 2; bool allHidden = true; for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { @@ -992,7 +1010,7 @@ int RenderTable::outerBorderRight() const if (tb.style() == BHIDDEN) return 0; if (tb.style() > BHIDDEN) - borderWidth = (tb.width + 1) / 2; + borderWidth = (tb.width() + 1) / 2; bool allHidden = true; for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h index d07a727..ea81d64 100644 --- a/WebCore/rendering/RenderTable.h +++ b/WebCore/rendering/RenderTable.h @@ -113,6 +113,7 @@ public: } RenderTableCol* colElement(int col, bool* startEdge = 0, bool* endEdge = 0) const; + RenderTableCol* nextColElement(RenderTableCol* current) const; bool needsSectionRecalc() const { return m_needsSectionRecalc; } void setNeedsSectionRecalc() diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index de71796..4506e77 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -88,18 +88,42 @@ void RenderTableCell::updateFromElement() Length RenderTableCell::styleOrColWidth() const { Length w = style()->width(); - if (colSpan() > 1 || !w.isAuto()) + if (!w.isAuto()) return w; + RenderTableCol* tableCol = table()->colElement(col()); + if (tableCol) { - w = tableCol->style()->width(); - + int colSpanCount = colSpan(); + + Length colWidthSum = Length(0, Fixed); + for (int i = 1; i <= colSpanCount; i++) { + Length colWidth = tableCol->style()->width(); + + // Percentage value should be returned only for colSpan == 1. + // Otherwise we return original width for the cell. + if (!colWidth.isFixed()) { + if (colSpanCount > 1) + return w; + return colWidth; + } + + colWidthSum = Length(colWidthSum.value() + colWidth.value(), Fixed); + + tableCol = table()->nextColElement(tableCol); + // If no next <col> tag found for the span we just return what we have for now. + if (!tableCol) + break; + } + // Column widths specified on <col> apply to the border box of the cell. // Percentages don't need to be handled since they're always treated this way (even when specified on the cells). // See Bugzilla bug 8126 for details. - if (w.isFixed() && w.value() > 0) - w = Length(max(0, w.value() - borderLeft() - borderRight() - paddingLeft() - paddingRight()), Fixed); + if (colWidthSum.isFixed() && colWidthSum.value() > 0) + colWidthSum = Length(max(0, colWidthSum.value() - borderLeft() - borderRight() - paddingLeft() - paddingRight()), Fixed); + return colWidthSum; } + return w; } @@ -312,7 +336,7 @@ static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1, return border1.style() > border2.style() ? border1 : border2; // The border have the same width and style. Rely on precedence (cell over row over row group, etc.) - return border1.precedence >= border2.precedence ? border1 : border2; + return border1.precedence() >= border2.precedence() ? border1 : border2; } CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const @@ -328,22 +352,25 @@ CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const // For border left, we need to check, in order of precedence: // (1) Our left border. - CollapsedBorderValue result(&style()->borderLeft(), BCELL); + int left = CSSPropertyBorderLeftColor; + int right = CSSPropertyBorderRightColor; + CollapsedBorderValue result(&style()->borderLeft(), style()->visitedDependentColor(left), BCELL); // (2) The right border of the cell to the left. RenderTableCell* prevCell = rtl ? tableElt->cellAfter(this) : tableElt->cellBefore(this); if (prevCell) { - result = rtl ? compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL)) : compareBorders(CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL), result); + CollapsedBorderValue prevCellBorder = CollapsedBorderValue(&prevCell->style()->borderRight(), prevCell->style()->visitedDependentColor(right), BCELL); + result = rtl ? compareBorders(result, prevCellBorder) : compareBorders(prevCellBorder, result); if (!result.exists()) return result; } else if (leftmostColumn) { // (3) Our row's left border. - result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW)); + result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), parent()->style()->visitedDependentColor(left), BROW)); if (!result.exists()) return result; // (4) Our row group's left border. - result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderLeft(), BROWGROUP)); + result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderLeft(), section()->style()->visitedDependentColor(left), BROWGROUP)); if (!result.exists()) return result; } @@ -353,11 +380,11 @@ CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const bool endColEdge; RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? colSpan() - 1 : 0), &startColEdge, &endColEdge); if (colElt && (!rtl ? startColEdge : endColEdge)) { - result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL)); + result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), colElt->style()->visitedDependentColor(left), BCOL)); if (!result.exists()) return result; if (colElt->parent()->isTableCol() && (!rtl ? !colElt->previousSibling() : !colElt->nextSibling())) { - result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderLeft(), BCOLGROUP)); + result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderLeft(), colElt->parent()->style()->visitedDependentColor(left), BCOLGROUP)); if (!result.exists()) return result; } @@ -367,13 +394,14 @@ CollapsedBorderValue RenderTableCell::collapsedLeftBorder(bool rtl) const if (!leftmostColumn) { colElt = tableElt->colElement(col() + (rtl ? colSpan() : -1), &startColEdge, &endColEdge); if (colElt && (!rtl ? endColEdge : startColEdge)) { - result = rtl ? compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL)) : compareBorders(CollapsedBorderValue(&colElt->style()->borderRight(), BCOL), result); + CollapsedBorderValue rightBorder = CollapsedBorderValue(&colElt->style()->borderRight(), colElt->style()->visitedDependentColor(right), BCOL); + result = rtl ? compareBorders(result, rightBorder) : compareBorders(rightBorder, result); if (!result.exists()) return result; } } else { // (7) The table's left border. - result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderLeft(), BTABLE)); + result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderLeft(), tableElt->style()->visitedDependentColor(left), BTABLE)); if (!result.exists()) return result; } @@ -394,24 +422,27 @@ CollapsedBorderValue RenderTableCell::collapsedRightBorder(bool rtl) const // For border right, we need to check, in order of precedence: // (1) Our right border. - CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL); + int left = CSSPropertyBorderLeftColor; + int right = CSSPropertyBorderRightColor; + CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), style()->visitedDependentColor(right), BCELL); // (2) The left border of the cell to the right. if (!rightmostColumn) { RenderTableCell* nextCell = rtl ? tableElt->cellBefore(this) : tableElt->cellAfter(this); if (nextCell && nextCell->style()) { - result = rtl ? compareBorders(CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL), result) : compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL)); + CollapsedBorderValue leftBorder = CollapsedBorderValue(&nextCell->style()->borderLeft(), nextCell->style()->visitedDependentColor(left), BCELL); + result = rtl ? compareBorders(leftBorder, result) : compareBorders(result, leftBorder); if (!result.exists()) return result; } } else { // (3) Our row's right border. - result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW)); + result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), parent()->style()->visitedDependentColor(right), BROW)); if (!result.exists()) return result; // (4) Our row group's right border. - result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderRight(), BROWGROUP)); + result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderRight(), section()->style()->visitedDependentColor(right), BROWGROUP)); if (!result.exists()) return result; } @@ -421,11 +452,11 @@ CollapsedBorderValue RenderTableCell::collapsedRightBorder(bool rtl) const bool endColEdge; RenderTableCol* colElt = tableElt->colElement(col() + (rtl ? 0 : colSpan() - 1), &startColEdge, &endColEdge); if (colElt && (!rtl ? endColEdge : startColEdge)) { - result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL)); + result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), colElt->style()->visitedDependentColor(right), BCOL)); if (!result.exists()) return result; if (colElt->parent()->isTableCol() && (!rtl ? !colElt->nextSibling() : !colElt->previousSibling())) { - result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderRight(), BCOLGROUP)); + result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderRight(), colElt->parent()->style()->visitedDependentColor(right), BCOLGROUP)); if (!result.exists()) return result; } @@ -435,13 +466,14 @@ CollapsedBorderValue RenderTableCell::collapsedRightBorder(bool rtl) const if (!rightmostColumn) { colElt = tableElt->colElement(col() + (rtl ? -1 : colSpan()), &startColEdge, &endColEdge); if (colElt && (!rtl ? startColEdge : endColEdge)) { - result = rtl ? compareBorders(CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL), result) : compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL)); + CollapsedBorderValue leftBorder = CollapsedBorderValue(&colElt->style()->borderLeft(), colElt->style()->visitedDependentColor(left), BCOL); + result = rtl ? compareBorders(leftBorder, result) : compareBorders(result, leftBorder); if (!result.exists()) return result; } } else { // (7) The table's right border. - result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE)); + result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), tableElt->style()->visitedDependentColor(right), BTABLE)); if (!result.exists()) return result; } @@ -453,18 +485,20 @@ CollapsedBorderValue RenderTableCell::collapsedTopBorder() const { // For border top, we need to check, in order of precedence: // (1) Our top border. - CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL); + int top = CSSPropertyBorderTopColor; + int bottom = CSSPropertyBorderBottomColor; + CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), style()->visitedDependentColor(top), BCELL); RenderTableCell* prevCell = table()->cellAbove(this); if (prevCell) { // (2) A previous cell's bottom border. - result = compareBorders(CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL), result); + result = compareBorders(CollapsedBorderValue(&prevCell->style()->borderBottom(), prevCell->style()->visitedDependentColor(bottom), BCELL), result); if (!result.exists()) return result; } // (3) Our row's top border. - result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW)); + result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), parent()->style()->visitedDependentColor(top), BROW)); if (!result.exists()) return result; @@ -477,7 +511,7 @@ CollapsedBorderValue RenderTableCell::collapsedTopBorder() const prevRow = prevCell->section()->lastChild(); if (prevRow) { - result = compareBorders(CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW), result); + result = compareBorders(CollapsedBorderValue(&prevRow->style()->borderBottom(), prevRow->style()->visitedDependentColor(bottom), BROW), result); if (!result.exists()) return result; } @@ -487,14 +521,14 @@ CollapsedBorderValue RenderTableCell::collapsedTopBorder() const RenderTableSection* currSection = section(); if (!row()) { // (5) Our row group's top border. - result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP)); + result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), currSection->style()->visitedDependentColor(top), BROWGROUP)); if (!result.exists()) return result; // (6) Previous row group's bottom border. currSection = table()->sectionAbove(currSection); if (currSection) { - result = compareBorders(CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP), result); + result = compareBorders(CollapsedBorderValue(&currSection->style()->borderBottom(), currSection->style()->visitedDependentColor(bottom), BROWGROUP), result); if (!result.exists()) return result; } @@ -504,18 +538,19 @@ CollapsedBorderValue RenderTableCell::collapsedTopBorder() const // (8) Our column and column group's top borders. RenderTableCol* colElt = table()->colElement(col()); if (colElt) { - result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), BCOL)); + result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), colElt->style()->visitedDependentColor(top), BCOL)); if (!result.exists()) return result; if (colElt->parent()->isTableCol()) { - result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderTop(), BCOLGROUP)); + result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderTop(), colElt->parent()->style()->visitedDependentColor(top), BCOLGROUP)); if (!result.exists()) return result; } } // (9) The table's top border. - result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderTop(), BTABLE)); + RenderTable* enclosingTable = table(); + result = compareBorders(result, CollapsedBorderValue(&enclosingTable->style()->borderTop(), enclosingTable->style()->visitedDependentColor(top), BTABLE)); if (!result.exists()) return result; } @@ -527,24 +562,26 @@ CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const { // For border top, we need to check, in order of precedence: // (1) Our bottom border. - CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), BCELL); + int top = CSSPropertyBorderTopColor; + int bottom = CSSPropertyBorderBottomColor; + CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), style()->visitedDependentColor(bottom), BCELL); RenderTableCell* nextCell = table()->cellBelow(this); if (nextCell) { // (2) A following cell's top border. - result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), BCELL)); + result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), nextCell->style()->visitedDependentColor(top), BCELL)); if (!result.exists()) return result; } // (3) Our row's bottom border. (FIXME: Deal with rowspan!) - result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), BROW)); + result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), parent()->style()->visitedDependentColor(bottom), BROW)); if (!result.exists()) return result; // (4) The next row's top border. if (nextCell) { - result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), BROW)); + result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), nextCell->parent()->style()->visitedDependentColor(top), BROW)); if (!result.exists()) return result; } @@ -553,14 +590,14 @@ CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const RenderTableSection* currSection = section(); if (row() + rowSpan() >= currSection->numRows()) { // (5) Our row group's bottom border. - result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP)); + result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), currSection->style()->visitedDependentColor(bottom), BROWGROUP)); if (!result.exists()) return result; // (6) Following row group's top border. currSection = table()->sectionBelow(currSection); if (currSection) { - result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP)); + result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), currSection->style()->visitedDependentColor(top), BROWGROUP)); if (!result.exists()) return result; } @@ -570,17 +607,18 @@ CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const // (8) Our column and column group's bottom borders. RenderTableCol* colElt = table()->colElement(col()); if (colElt) { - result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), BCOL)); + result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), colElt->style()->visitedDependentColor(bottom), BCOL)); if (!result.exists()) return result; if (colElt->parent()->isTableCol()) { - result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderBottom(), BCOLGROUP)); + result = compareBorders(result, CollapsedBorderValue(&colElt->parent()->style()->borderBottom(), colElt->parent()->style()->visitedDependentColor(bottom), BCOLGROUP)); if (!result.exists()) return result; } } // (9) The table's bottom border. - result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderBottom(), BTABLE)); + RenderTable* enclosingTable = table(); + result = compareBorders(result, CollapsedBorderValue(&enclosingTable->style()->borderBottom(), enclosingTable->style()->visitedDependentColor(bottom), BTABLE)); if (!result.exists()) return result; } @@ -811,7 +849,7 @@ void RenderTableCell::paintCollapsedBorder(GraphicsContext* graphicsContext, int for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) { if (border->borderValue == *table()->currentBorderStyle()) drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side, - border->borderValue.color(), style()->color(), border->style, 0, 0); + border->borderValue.color(), border->style, 0, 0); } } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index a2457e1..e8ab4a4 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -807,13 +807,13 @@ int RenderTableSection::calcOuterBorderTop() const if (sb.style() == BHIDDEN) return -1; if (sb.style() > BHIDDEN) - borderWidth = sb.width; + borderWidth = sb.width(); const BorderValue& rb = firstChild()->style()->borderTop(); if (rb.style() == BHIDDEN) return -1; - if (rb.style() > BHIDDEN && rb.width > borderWidth) - borderWidth = rb.width; + if (rb.style() > BHIDDEN && rb.width() > borderWidth) + borderWidth = rb.width(); bool allHidden = true; for (int c = 0; c < totalCols; c++) { @@ -829,17 +829,17 @@ int RenderTableSection::calcOuterBorderTop() const continue; else allHidden = false; - if (gb.style() > BHIDDEN && gb.width > borderWidth) - borderWidth = gb.width; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; + if (gb.style() > BHIDDEN && gb.width() > borderWidth) + borderWidth = gb.width(); + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); } else { if (cb.style() == BHIDDEN) continue; else allHidden = false; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); } } if (allHidden) @@ -860,13 +860,13 @@ int RenderTableSection::calcOuterBorderBottom() const if (sb.style() == BHIDDEN) return -1; if (sb.style() > BHIDDEN) - borderWidth = sb.width; + borderWidth = sb.width(); const BorderValue& rb = lastChild()->style()->borderBottom(); if (rb.style() == BHIDDEN) return -1; - if (rb.style() > BHIDDEN && rb.width > borderWidth) - borderWidth = rb.width; + if (rb.style() > BHIDDEN && rb.width() > borderWidth) + borderWidth = rb.width(); bool allHidden = true; for (int c = 0; c < totalCols; c++) { @@ -882,17 +882,17 @@ int RenderTableSection::calcOuterBorderBottom() const continue; else allHidden = false; - if (gb.style() > BHIDDEN && gb.width > borderWidth) - borderWidth = gb.width; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; + if (gb.style() > BHIDDEN && gb.width() > borderWidth) + borderWidth = gb.width(); + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); } else { if (cb.style() == BHIDDEN) continue; else allHidden = false; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); } } if (allHidden) @@ -913,7 +913,7 @@ int RenderTableSection::calcOuterBorderLeft(bool rtl) const if (sb.style() == BHIDDEN) return -1; if (sb.style() > BHIDDEN) - borderWidth = sb.width; + borderWidth = sb.width(); int leftmostColumn = rtl ? totalCols - 1 : 0; RenderTableCol* colGroup = table()->colElement(leftmostColumn); @@ -921,8 +921,8 @@ int RenderTableSection::calcOuterBorderLeft(bool rtl) const const BorderValue& gb = colGroup->style()->borderLeft(); if (gb.style() == BHIDDEN) return -1; - if (gb.style() > BHIDDEN && gb.width > borderWidth) - borderWidth = gb.width; + if (gb.style() > BHIDDEN && gb.width() > borderWidth) + borderWidth = gb.width(); } bool allHidden = true; @@ -937,10 +937,10 @@ int RenderTableSection::calcOuterBorderLeft(bool rtl) const continue; else allHidden = false; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; - if (rb.style() > BHIDDEN && rb.width > borderWidth) - borderWidth = rb.width; + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); + if (rb.style() > BHIDDEN && rb.width() > borderWidth) + borderWidth = rb.width(); } if (allHidden) return -1; @@ -960,7 +960,7 @@ int RenderTableSection::calcOuterBorderRight(bool rtl) const if (sb.style() == BHIDDEN) return -1; if (sb.style() > BHIDDEN) - borderWidth = sb.width; + borderWidth = sb.width(); int rightmostColumn = rtl ? 0 : totalCols - 1; RenderTableCol* colGroup = table()->colElement(rightmostColumn); @@ -968,8 +968,8 @@ int RenderTableSection::calcOuterBorderRight(bool rtl) const const BorderValue& gb = colGroup->style()->borderRight(); if (gb.style() == BHIDDEN) return -1; - if (gb.style() > BHIDDEN && gb.width > borderWidth) - borderWidth = gb.width; + if (gb.style() > BHIDDEN && gb.width() > borderWidth) + borderWidth = gb.width(); } bool allHidden = true; @@ -984,10 +984,10 @@ int RenderTableSection::calcOuterBorderRight(bool rtl) const continue; else allHidden = false; - if (cb.style() > BHIDDEN && cb.width > borderWidth) - borderWidth = cb.width; - if (rb.style() > BHIDDEN && rb.width > borderWidth) - borderWidth = rb.width; + if (cb.style() > BHIDDEN && cb.width() > borderWidth) + borderWidth = cb.width(); + if (rb.style() > BHIDDEN && rb.width() > borderWidth) + borderWidth = rb.width(); } if (allHidden) return -1; diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 4653273..90ad6d8 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -36,8 +36,10 @@ #include "RenderBlock.h" #include "RenderLayer.h" #include "RenderView.h" +#include "StringBuffer.h" #include "Text.h" #include "TextBreakIterator.h" +#include "TextResourceDecoder.h" #include "VisiblePosition.h" #include "break_lines.h" #include <wtf/AlwaysInline.h> @@ -48,16 +50,46 @@ using namespace Unicode; namespace WebCore { -// FIXME: Move to StringImpl.h eventually. -static inline bool charactersAreAllASCII(StringImpl* text) +static void makeCapitalized(String* string, UChar previous) { - return charactersAreAllASCII(text->characters(), text->length()); + if (string->isNull()) + return; + + unsigned length = string->length(); + const UChar* characters = string->characters(); + + StringBuffer stringWithPrevious(length + 1); + stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; + for (unsigned i = 1; i < length + 1; i++) { + // Replace   with a real space since ICU no longer treats   as a word separator. + if (characters[i - 1] == noBreakSpace) + stringWithPrevious[i] = ' '; + else + stringWithPrevious[i] = characters[i - 1]; + } + + TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), length + 1); + if (!boundary) + return; + + StringBuffer data(length); + + int32_t endOfWord; + int32_t startOfWord = textBreakFirst(boundary); + for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) { + if (startOfWord != 0) // Ignore first char of previous string + data[startOfWord - 1] = characters[startOfWord - 1] == noBreakSpace ? noBreakSpace : toTitleCase(stringWithPrevious[startOfWord]); + for (int i = startOfWord + 1; i < endOfWord; i++) + data[i - 1] = characters[i - 1]; + } + + *string = String::adopt(data); } RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str) : RenderObject(node) , m_minWidth(-1) - , m_text(document()->displayStringModifiedByEncoding(str)) + , m_text(str) , m_firstTextBox(0) , m_lastTextBox(0) , m_maxWidth(-1) @@ -66,8 +98,9 @@ RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str) , m_hasTab(false) , m_linesDirty(false) , m_containsReversedText(false) - , m_isAllASCII(charactersAreAllASCII(m_text.get())) - , m_knownNotToUseFallbackFonts(false) + , m_isAllASCII(m_text.containsOnlyASCII()) + , m_knownToHaveNoOverflowAndNoFallbackFonts(false) + , m_needsTranscoding(false) { ASSERT(m_text); @@ -104,6 +137,11 @@ bool RenderText::isWordBreak() const return false; } +void RenderText::updateNeedsTranscoding() +{ + m_needsTranscoding = document()->decoder() && document()->decoder()->encoding().backslashAsCurrencySymbol() != '\\'; +} + void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { // There is no need to ever schedule repaints from a style change of a text run, since @@ -112,13 +150,18 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl // need to relayout. if (diff == StyleDifferenceLayout) { setNeedsLayoutAndPrefWidthsRecalc(); - m_knownNotToUseFallbackFonts = false; + m_knownToHaveNoOverflowAndNoFallbackFonts = false; + } + + bool needsResetText = false; + if (!oldStyle) { + updateNeedsTranscoding(); + needsResetText = m_needsTranscoding; } ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE; ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE; - - if (oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()) { + if (needsResetText || oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()) { if (RefPtr<StringImpl> textToTransform = originalText()) setText(textToTransform.release(), true); } @@ -150,9 +193,9 @@ void RenderText::extractTextBox(InlineTextBox* box) if (box == m_firstTextBox) m_firstTextBox = 0; if (box->prevTextBox()) - box->prevTextBox()->setNextLineBox(0); - box->setPreviousLineBox(0); - for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox()) + box->prevTextBox()->setNextTextBox(0); + box->setPreviousTextBox(0); + for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) curr->setExtracted(); checkConsistency(); @@ -163,8 +206,8 @@ void RenderText::attachTextBox(InlineTextBox* box) checkConsistency(); if (m_lastTextBox) { - m_lastTextBox->setNextLineBox(box); - box->setPreviousLineBox(m_lastTextBox); + m_lastTextBox->setNextTextBox(box); + box->setPreviousTextBox(m_lastTextBox); } else m_firstTextBox = box; InlineTextBox* last = box; @@ -186,9 +229,9 @@ void RenderText::removeTextBox(InlineTextBox* box) if (box == m_lastTextBox) m_lastTextBox = box->prevTextBox(); if (box->nextTextBox()) - box->nextTextBox()->setPreviousLineBox(box->prevTextBox()); + box->nextTextBox()->setPreviousTextBox(box->prevTextBox()); if (box->prevTextBox()) - box->prevTextBox()->setNextLineBox(box->nextTextBox()); + box->prevTextBox()->setNextTextBox(box->nextTextBox()); checkConsistency(); } @@ -434,7 +477,7 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e return IntRect(left, top, caretWidth, height); } -ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const +ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) { int monospaceCharacterWidth = f.spaceWidth(); @@ -442,8 +485,10 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int w = 0; bool isSpace; bool previousCharWasSpace = true; // FIXME: Preserves historical behavior, but seems wrong for start > 0. + ASSERT(m_text); + StringImpl& text = *m_text.impl(); for (int i = start; i < start + len; i++) { - char c = (*m_text)[i]; + char c = text[i]; if (c <= ' ') { if (c == ' ' || c == '\n') { w += monospaceCharacterWidth; @@ -464,7 +509,7 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, return w; } - return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos), fallbackFonts); + return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos), fallbackFonts, glyphOverflow); } void RenderText::trimmedPrefWidths(int leadWidth, @@ -486,7 +531,7 @@ void RenderText::trimmedPrefWidths(int leadWidth, int len = textLength(); - if (!len || (stripFrontSpaces && m_text->containsOnlyWhitespace())) { + if (!len || (stripFrontSpaces && text()->containsOnlyWhitespace())) { beginMinW = 0; endMinW = 0; beginMaxW = 0; @@ -506,7 +551,9 @@ void RenderText::trimmedPrefWidths(int leadWidth, hasBreakableChar = m_hasBreakableChar; hasBreak = m_hasBreak; - if ((*m_text)[0] == ' ' || ((*m_text)[0] == '\n' && !style()->preserveNewline()) || (*m_text)[0] == '\t') { + ASSERT(m_text); + StringImpl& text = *m_text.impl(); + if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || text[0] == '\t') { const Font& f = style()->font(); // FIXME: This ignores first-line. if (stripFrontSpaces) { const UChar space = ' '; @@ -529,11 +576,11 @@ void RenderText::trimmedPrefWidths(int leadWidth, endMaxW = maxW; for (int i = 0; i < len; i++) { int linelen = 0; - while (i + linelen < len && (*m_text)[i + linelen] != '\n') + while (i + linelen < len && text[i + linelen] != '\n') linelen++; if (linelen) { - endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0); + endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0, 0); if (firstLine) { firstLine = false; leadWidth = 0; @@ -578,14 +625,15 @@ int RenderText::maxPrefWidth() const void RenderText::calcPrefWidths(int leadWidth) { HashSet<const SimpleFontData*> fallbackFonts; - calcPrefWidths(leadWidth, fallbackFonts); - if (fallbackFonts.isEmpty()) - m_knownNotToUseFallbackFonts = true; + GlyphOverflow glyphOverflow; + calcPrefWidths(leadWidth, fallbackFonts, glyphOverflow); + if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom) + m_knownToHaveNoOverflowAndNoFallbackFonts = true; } -void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts) +void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow) { - ASSERT(m_hasTab || prefWidthsDirty() || !m_knownNotToUseFallbackFonts); + ASSERT(m_hasTab || prefWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts); m_minWidth = 0; m_beginMinWidth = 0; @@ -615,6 +663,8 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f int nextBreakable = -1; int lastWordBoundary = 0; + int firstGlyphLeftOverflow = -1; + bool breakNBSP = style()->autoWrap() && style()->nbspMode() == SPACE; bool breakAll = (style()->wordBreak() == BreakAllWordBreak || style()->wordBreak() == BreakWordBreak) && style()->autoWrap(); @@ -657,7 +707,9 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f lastWordBoundary++; continue; } else if (c == softHyphen) { - currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts); + currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); + if (firstGlyphLeftOverflow < 0) + firstGlyphLeftOverflow = glyphOverflow.left; lastWordBoundary = i + 1; continue; } @@ -680,13 +732,15 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f int wordLen = j - i; if (wordLen) { - int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts); + int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); + if (firstGlyphLeftOverflow < 0) + firstGlyphLeftOverflow = glyphOverflow.left; currMinWidth += w; if (betweenWords) { if (lastWordBoundary == i) currMaxWidth += w; else - currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts); + currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); lastWordBoundary = j; } @@ -739,6 +793,7 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f currMaxWidth = 0; } else { currMaxWidth += f.width(TextRun(txt + i, 1, allowTabs(), leadWidth + currMaxWidth)); + glyphOverflow.right = 0; needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1; } ASSERT(lastWordBoundary == i); @@ -746,6 +801,9 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f } } + if (firstGlyphLeftOverflow > 0) + glyphOverflow.left = firstGlyphLeftOverflow; + if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord)) currMaxWidth += wordSpacing; @@ -777,9 +835,11 @@ bool RenderText::isAllCollapsibleWhitespace() bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const { + ASSERT(m_text); + StringImpl& text = *m_text.impl(); unsigned currPos; for (currPos = from; - currPos < from + len && ((*m_text)[currPos] == '\n' || (*m_text)[currPos] == ' ' || (*m_text)[currPos] == '\t'); + currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' ' || text[currPos] == '\t'); currPos++) { } return currPos >= (from + len); } @@ -912,7 +972,7 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, setText(text, force); } -static inline bool isInlineFlowOrEmptyText(RenderObject* o) +static inline bool isInlineFlowOrEmptyText(const RenderObject* o) { if (o->isRenderInline()) return true; @@ -924,10 +984,10 @@ static inline bool isInlineFlowOrEmptyText(RenderObject* o) return !text->length(); } -UChar RenderText::previousCharacter() +UChar RenderText::previousCharacter() const { // find previous text renderer if one exists - RenderObject* previousText = this; + const RenderObject* previousText = this; while ((previousText = previousText->previousInPreOrder())) if (!isInlineFlowOrEmptyText(previousText)) break; @@ -938,10 +998,31 @@ UChar RenderText::previousCharacter() return prev; } +void RenderText::transformText(String& text) const +{ + ASSERT(style()); + switch (style()->textTransform()) { + case TTNONE: + break; + case CAPITALIZE: + makeCapitalized(&text, previousCharacter()); + break; + case UPPERCASE: + text.makeUpper(); + break; + case LOWERCASE: + text.makeLower(); + break; + } +} + void RenderText::setTextInternal(PassRefPtr<StringImpl> text) { ASSERT(text); - m_text = document()->displayStringModifiedByEncoding(text); + if (m_needsTranscoding) + m_text = document()->displayStringModifiedByEncoding(text); + else + m_text = text; ASSERT(m_text); #if ENABLE(SVG) @@ -952,7 +1033,7 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text) // characters into space characters. Then, it will draw all space characters, including // leading, trailing and multiple contiguous space characters. - m_text = m_text->replace('\n', ' '); + m_text.replace('\n', ' '); // If xml:space="preserve" is set, white-space is set to "pre", which // preserves leading, trailing & contiguous space character for us. @@ -963,70 +1044,71 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text) // Then, it will strip off all leading and trailing space characters. // Then, all contiguous space characters will be consolidated. - m_text = m_text->replace('\n', StringImpl::empty()); + m_text.replace('\n', StringImpl::empty()); // If xml:space="default" is set, white-space is set to "nowrap", which handles // leading, trailing & contiguous space character removal for us. } - m_text = m_text->replace('\t', ' '); + m_text.replace('\t', ' '); } #endif if (style()) { - switch (style()->textTransform()) { - case TTNONE: - break; - case CAPITALIZE: { - m_text = m_text->capitalize(previousCharacter()); - break; - } - case UPPERCASE: - m_text = m_text->upper(); - break; - case LOWERCASE: - m_text = m_text->lower(); - break; - } + transformText(m_text); // We use the same characters here as for list markers. // See the listMarkerText function in RenderListMarker.cpp. switch (style()->textSecurity()) { - case TSNONE: - break; - case TSCIRCLE: - m_text = m_text->secure(whiteBullet); - break; - case TSDISC: - m_text = m_text->secure(bullet); - break; - case TSSQUARE: - m_text = m_text->secure(blackSquare); + case TSNONE: + break; + case TSCIRCLE: + m_text.makeSecure(whiteBullet); + break; + case TSDISC: + m_text.makeSecure(bullet); + break; + case TSSQUARE: + m_text.makeSecure(blackSquare); } } ASSERT(m_text); - ASSERT(!isBR() || (textLength() == 1 && (*m_text)[0] == '\n')); + ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n')); - m_isAllASCII = charactersAreAllASCII(m_text.get()); + m_isAllASCII = m_text.containsOnlyASCII(); } void RenderText::setText(PassRefPtr<StringImpl> text, bool force) { ASSERT(text); - if (!force && equal(m_text.get(), text.get())) + if (!force && equal(m_text.impl(), text.get())) return; setTextInternal(text); setNeedsLayoutAndPrefWidthsRecalc(); - m_knownNotToUseFallbackFonts = false; + m_knownToHaveNoOverflowAndNoFallbackFonts = false; AXObjectCache* axObjectCache = document()->axObjectCache(); if (axObjectCache->accessibilityEnabled()) axObjectCache->contentChanged(this); } +String RenderText::textWithoutTranscoding() const +{ + // If m_text isn't transcoded or is secure, we can just return the modified text. + if (!m_needsTranscoding || style()->textSecurity() != TSNONE) + return text(); + + // Otherwise, we should use original text. If text-transform is + // specified, we should transform the text on the fly. + String text = originalText(); + if (style()) + transformText(text); + return text; +} + int RenderText::lineHeight(bool firstLine, bool) const { // Always use the interior line height of the parent (e.g., if our parent is an inline block). @@ -1055,8 +1137,8 @@ InlineTextBox* RenderText::createInlineTextBox() if (!m_firstTextBox) m_firstTextBox = m_lastTextBox = textBox; else { - m_lastTextBox->setNextLineBox(textBox); - textBox->setPreviousLineBox(m_lastTextBox); + m_lastTextBox->setNextTextBox(textBox); + textBox->setPreviousTextBox(m_lastTextBox); m_lastTextBox = textBox; } textBox->setIsText(true); @@ -1074,11 +1156,11 @@ void RenderText::positionLineBox(InlineBox* box) if (m_firstTextBox == s) m_firstTextBox = s->nextTextBox(); else - s->prevTextBox()->setNextLineBox(s->nextTextBox()); + s->prevTextBox()->setNextTextBox(s->nextTextBox()); if (m_lastTextBox == s) m_lastTextBox = s->prevTextBox(); else - s->nextTextBox()->setPreviousLineBox(s->prevTextBox()); + s->nextTextBox()->setPreviousTextBox(s->prevTextBox()); s->destroy(renderArena()); return; } @@ -1086,7 +1168,7 @@ void RenderText::positionLineBox(InlineBox* box) m_containsReversedText |= s->direction() == RTL; } -unsigned RenderText::width(unsigned from, unsigned len, int xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts) const +unsigned RenderText::width(unsigned from, unsigned len, int xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { if (from >= textLength()) return 0; @@ -1094,10 +1176,10 @@ unsigned RenderText::width(unsigned from, unsigned len, int xPos, bool firstLine if (from + len > textLength()) len = textLength() - from; - return width(from, len, style(firstLine)->font(), xPos, fallbackFonts); + return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow); } -unsigned RenderText::width(unsigned from, unsigned len, const Font& f, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const +unsigned RenderText::width(unsigned from, unsigned len, const Font& f, int xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { ASSERT(from + len <= textLength()); if (!characters()) @@ -1107,18 +1189,19 @@ unsigned RenderText::width(unsigned from, unsigned len, const Font& f, int xPos, if (&f == &style()->font()) { if (!style()->preserveNewline() && !from && len == textLength()) { if (fallbackFonts) { - if (prefWidthsDirty() || !m_knownNotToUseFallbackFonts) { - const_cast<RenderText*>(this)->calcPrefWidths(0, *fallbackFonts); - if (fallbackFonts->isEmpty()) - m_knownNotToUseFallbackFonts = true; + ASSERT(glyphOverflow); + if (prefWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) { + const_cast<RenderText*>(this)->calcPrefWidths(0, *fallbackFonts, *glyphOverflow); + if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom) + m_knownToHaveNoOverflowAndNoFallbackFonts = true; } w = m_maxWidth; } else w = maxPrefWidth(); } else - w = widthFromCache(f, from, len, xPos, fallbackFonts); + w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow); } else - w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos), fallbackFonts); + w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos), fallbackFonts, glyphOverflow); return w; } @@ -1150,6 +1233,11 @@ IntRect RenderText::linesBoundingBox() const IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { RenderObject* cb = containingBlock(); + // The containing block may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint. + if (repaintContainer && repaintContainer != cb) { + if (!cb->isDescendantOf(repaintContainer)) + return repaintContainer->clippedOverflowRectForRepaint(repaintContainer); + } return cb->clippedOverflowRectForRepaint(repaintContainer); } @@ -1245,7 +1333,7 @@ unsigned RenderText::caretMaxRenderedOffset() const int RenderText::previousOffset(int current) const { - StringImpl* si = m_text.get(); + StringImpl* si = m_text.impl(); TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length()); if (!iterator) return current - 1; @@ -1293,14 +1381,16 @@ inline bool isHangulLVT(UChar32 character) int RenderText::previousOffsetForBackwardDeletion(int current) const { #if PLATFORM(MAC) + ASSERT(m_text); + StringImpl& text = *m_text.impl(); UChar32 character; while (current > 0) { - if (U16_IS_TRAIL((*m_text)[--current])) + if (U16_IS_TRAIL(text[--current])) --current; if (current < 0) break; - UChar32 character = m_text->characterStartingAt(current); + UChar32 character = text.characterStartingAt(current); // We don't combine characters in Armenian ... Limbu range for backward deletion. if ((character >= 0x0530) && (character < 0x1950)) @@ -1314,7 +1404,7 @@ int RenderText::previousOffsetForBackwardDeletion(int current) const return current; // Hangul - character = m_text->characterStartingAt(current); + character = text.characterStartingAt(current); if (((character >= HANGUL_CHOSEONG_START) && (character <= HANGUL_JONGSEONG_END)) || ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))) { HangulState state; HangulState initialState; @@ -1330,7 +1420,7 @@ int RenderText::previousOffsetForBackwardDeletion(int current) const initialState = state; - while (current > 0 && ((character = m_text->characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) { + while (current > 0 && ((character = text.characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) { switch (state) { case HangulStateV: if (character <= HANGUL_CHOSEONG_END) @@ -1368,7 +1458,7 @@ int RenderText::previousOffsetForBackwardDeletion(int current) const int RenderText::nextOffset(int current) const { - StringImpl* si = m_text.get(); + StringImpl* si = m_text.impl(); TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length()); if (!iterator) return current + 1; diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h index d46bce9..92c82e1 100644 --- a/WebCore/rendering/RenderText.h +++ b/WebCore/rendering/RenderText.h @@ -50,7 +50,8 @@ public: virtual void destroy(); - StringImpl* text() const { return m_text.get(); } + StringImpl* text() const { return m_text.impl(); } + String textWithoutTranscoding() const; InlineTextBox* createInlineTextBox(); void dirtyLineBoxes(bool fullLayout); @@ -63,12 +64,12 @@ public: virtual VisiblePosition positionForPoint(const IntPoint&); - const UChar* characters() const { return m_text->characters(); } - unsigned textLength() const { return m_text->length(); } // non virtual implementation of length() + const UChar* characters() const { return m_text.characters(); } + unsigned textLength() const { return m_text.length(); } // non virtual implementation of length() void positionLineBox(InlineBox*); - virtual unsigned width(unsigned from, unsigned len, const Font&, int xPos, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; - virtual unsigned width(unsigned from, unsigned len, int xPos, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; + virtual unsigned width(unsigned from, unsigned len, const Font&, int xPos, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; + virtual unsigned width(unsigned from, unsigned len, int xPos, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const; @@ -128,12 +129,12 @@ protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void setTextInternal(PassRefPtr<StringImpl>); - virtual UChar previousCharacter(); + virtual UChar previousCharacter() const; virtual InlineTextBox* createTextBox(); // Subclassed by SVG. private: - void calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts); + void calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow&); // Make length() private so that callers that have a RenderText* // will use the more efficient textLength() instead, while @@ -146,12 +147,15 @@ private: void deleteTextBoxes(); bool containsOnlyWhitespace(unsigned from, unsigned len) const; - int widthFromCache(const Font&, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const; + int widthFromCache(const Font&, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const; bool isAllASCII() const { return m_isAllASCII; } + void updateNeedsTranscoding(); + + inline void transformText(String&) const; int m_minWidth; // here to minimize padding in 64-bit. - RefPtr<StringImpl> m_text; + String m_text; InlineTextBox* m_firstTextBox; InlineTextBox* m_lastTextBox; @@ -171,7 +175,8 @@ private: // or removed). bool m_containsReversedText : 1; bool m_isAllASCII : 1; - mutable bool m_knownNotToUseFallbackFonts : 1; + mutable bool m_knownToHaveNoOverflowAndNoFallbackFonts : 1; + bool m_needsTranscoding : 1; }; inline RenderText* toRenderText(RenderObject* object) diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index d18940b..5e19362 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -167,15 +167,7 @@ void RenderTextControl::updateFromElement() void RenderTextControl::setInnerTextValue(const String& innerTextValue) { - String value; - - if (innerTextValue.isNull()) - value = ""; - else { - value = innerTextValue; - value = document()->displayStringModifiedByEncoding(value); - } - + String value = innerTextValue; if (value != text() || !m_innerText->hasChildNodes()) { if (value != text()) { if (Frame* frame = document()->frame()) { @@ -266,11 +258,6 @@ void RenderTextControl::setSelectionRange(int start, int end) if (Frame* frame = document()->frame()) frame->selection()->setSelection(newSelection); - - // FIXME: Granularity is stored separately on the frame, but also in the selection controller. - // The granularity in the selection controller should be used, and then this line of code would not be needed. - if (Frame* frame = document()->frame()) - frame->setSelectionGranularity(CharacterGranularity); } VisibleSelection RenderTextControl::selection(int start, int end) const @@ -323,9 +310,6 @@ String RenderTextControl::finishText(Vector<UChar>& result) const if (size && result[size - 1] == '\n') result.shrink(--size); - // Convert backslash to currency symbol. - document()->displayBufferModifiedByEncoding(result.data(), result.size()); - return String::adopt(result); } @@ -373,8 +357,6 @@ String RenderTextControl::textWithHardLineBreaks() if (!firstChild) return ""; - document()->updateLayout(); - RenderObject* renderer = firstChild->renderer(); if (!renderer) return ""; diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index aa1f1e3..e1bcc84 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -101,6 +101,7 @@ private: virtual void valueChanged(unsigned listIndex, bool fireEvents = true); virtual String itemText(unsigned listIndex) const; virtual String itemToolTip(unsigned) const { return String(); } + virtual String itemAccessibilityText(unsigned) const { return String(); } virtual bool itemIsEnabled(unsigned listIndex) const; virtual PopupMenuStyle itemStyle(unsigned listIndex) const; virtual PopupMenuStyle menuStyle() const; diff --git a/WebCore/rendering/RenderTextFragment.cpp b/WebCore/rendering/RenderTextFragment.cpp index 9ff1106..2164ae1 100644 --- a/WebCore/rendering/RenderTextFragment.cpp +++ b/WebCore/rendering/RenderTextFragment.cpp @@ -69,10 +69,14 @@ void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text) m_firstLetter = 0; m_start = 0; m_end = textLength(); + if (Node* t = node()) { + ASSERT(!t->renderer()); + t->setRenderer(this); + } } } -UChar RenderTextFragment::previousCharacter() +UChar RenderTextFragment::previousCharacter() const { if (start()) { Node* e = node(); diff --git a/WebCore/rendering/RenderTextFragment.h b/WebCore/rendering/RenderTextFragment.h index 1fa509a..e351436 100644 --- a/WebCore/rendering/RenderTextFragment.h +++ b/WebCore/rendering/RenderTextFragment.h @@ -51,7 +51,7 @@ public: private: virtual void setTextInternal(PassRefPtr<StringImpl>); - virtual UChar previousCharacter(); + virtual UChar previousCharacter() const; unsigned m_start; unsigned m_end; diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index f1e564b..b3b7a1e 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -213,6 +213,10 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El return adjustSearchFieldResultsDecorationStyle(selector, style, e); case SearchFieldResultsButtonPart: return adjustSearchFieldResultsButtonStyle(selector, style, e); +#if ENABLE(PROGRESS_TAG) + case ProgressBarPart: + return adjustProgressBarStyle(selector, style, e); +#endif default: break; } @@ -271,6 +275,10 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf #endif case MenulistPart: return paintMenuList(o, paintInfo, r); +#if ENABLE(PROGRESS_TAG) + case ProgressBarPart: + return paintProgressBar(o, paintInfo, r); +#endif case SliderHorizontalPart: case SliderVerticalPart: return paintSliderTrack(o, paintInfo, r); @@ -361,6 +369,9 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo case DefaultButtonPart: case ButtonPart: case MenulistPart: +#if ENABLE(PROGRESS_TAG) + case ProgressBarPart: +#endif case SliderHorizontalPart: case SliderVerticalPart: case SliderThumbHorizontalPart: @@ -396,6 +407,9 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf case DefaultButtonPart: case ButtonPart: case MenulistPart: +#if ENABLE(PROGRESS_TAG) + case ProgressBarPart: +#endif case SliderHorizontalPart: case SliderVerticalPart: case SliderThumbHorizontalPart: @@ -829,6 +843,22 @@ void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) { } +#if ENABLE(PROGRESS_TAG) +double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const +{ + return 0; +} + +double RenderTheme::animationDurationForProgressBar(RenderProgress*) const +{ + return 0; +} + +void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const +{ +} +#endif + void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const { } diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 32ae5e5..1526138 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -39,6 +39,9 @@ namespace WebCore { class Element; class PopupMenu; class RenderMenuList; +#if ENABLE(PROGRESS_TAG) +class RenderProgress; +#endif class CSSStyleSheet; class RenderTheme : public RefCounted<RenderTheme> { @@ -169,6 +172,13 @@ public: // Method for painting the caps lock indicator virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return 0; }; +#if ENABLE(PROGRESS_TAG) + // Returns the repeat interval of the animation for the progress bar. + virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const; + // Returns the duration of the animation for the progress bar. + virtual double animationDurationForProgressBar(RenderProgress*) const; +#endif + #if ENABLE(VIDEO) // Media controls virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint); @@ -230,6 +240,11 @@ protected: virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } +#if ENABLE(PROGRESS_TAG) + virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } +#endif + virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index 7d3bcec..8b3b388 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -403,28 +403,41 @@ void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelecto style->setHeight(Length(cancelButtonSize, Fixed)); } -bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, IntRect partRect, const IntRect& localOffset) const { - IntRect bounds = r; - ASSERT(o->parent()); - if (!o->parent() || !o->parent()->isBox()) - return false; - - RenderBox* parentRenderBox = toRenderBox(o->parent()); + // Compute an offset between the part renderer and the input renderer. + IntSize offsetFromInputRenderer = -(partRenderer->offsetFromAncestorContainer(inputRenderer)); + // Move the rect into partRenderer's coords. + partRect.move(offsetFromInputRenderer); + // Account for the local drawing offset. + partRect.move(localOffset.x(), localOffset.y()); - IntRect parentBox = parentRenderBox->absoluteContentBox(); + return partRect; +} - // Make sure the scaled button stays square and will fit in its parent's box - bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height()))); - bounds.setWidth(bounds.height()); +bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + // Get the renderer of <input> element. + Node* input = cancelButtonObject->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) + return false; + RenderBox* inputRenderBox = toRenderBox(input->renderer()); + IntRect inputContentBox = inputRenderBox->contentBoxRect(); + // Make sure the scaled button stays square and will fit in its parent's box. + int cancelButtonSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height())); + // Calculate cancel button's coordinates relative to the input element. // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will // be one pixel closer to the bottom of the field. This tends to look better with the text. - bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); + IntRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(), + inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2, + cancelButtonSize, cancelButtonSize); + IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r); static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef(); static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef(); - i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o->style()->colorSpace(), bounds); + paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage, + cancelButtonObject->style()->colorSpace(), paintingRect); return false; } @@ -445,26 +458,27 @@ void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSe style->setHeight(Length(magnifierSize, Fixed)); } -bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - IntRect bounds = r; - ASSERT(o->parent()); - if (!o->parent() || !o->parent()->isBox()) + // Get the renderer of <input> element. + Node* input = magnifierObject->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) return false; + RenderBox* inputRenderBox = toRenderBox(input->renderer()); + IntRect inputContentBox = inputRenderBox->contentBoxRect(); - RenderBox* parentRenderBox = toRenderBox(o->parent()); - IntRect parentBox = parentRenderBox->absoluteContentBox(); - - // Make sure the scaled decoration stays square and will fit in its parent's box - bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height()))); - bounds.setWidth(bounds.height()); - + // Make sure the scaled decoration stays square and will fit in its parent's box. + int magnifierSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height())); + // Calculate decoration's coordinates relative to the input element. // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will // be one pixel closer to the bottom of the field. This tends to look better with the text. - bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); + IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(), + inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2, + magnifierSize, magnifierSize); + IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef(); - i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); + paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect); return false; } @@ -479,28 +493,25 @@ void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelect style->setHeight(Length(magnifierHeight, Fixed)); } -bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnifierObject, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - IntRect bounds = r; - ASSERT(o->parent()); - if (!o->parent()) - return false; - if (!o->parent() || !o->parent()->isBox()) + // Get the renderer of <input> element. + Node* input = magnifierObject->node()->shadowAncestorNode(); + if (!input->renderer()->isBox()) return false; + RenderBox* inputRenderBox = toRenderBox(input->renderer()); + IntRect inputContentBox = inputRenderBox->contentBoxRect(); - RenderBox* parentRenderBox = toRenderBox(o->parent()); - IntRect parentBox = parentRenderBox->absoluteContentBox(); - - // Make sure the scaled decoration will fit in its parent's box - bounds.setHeight(std::min(parentBox.height(), bounds.height())); - bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize))); - - // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will - // be one pixel closer to the bottom of the field. This tends to look better with the text. - bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); + // Make sure the scaled decoration will fit in its parent's box. + int magnifierHeight = std::min(inputContentBox.height(), r.height()); + int magnifierWidth = std::min(inputContentBox.width(), static_cast<int>(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)); + IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(), + inputContentBox.y() + (inputContentBox.height() - magnifierHeight + 1) / 2, + magnifierWidth, magnifierHeight); + IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef(); - i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); + paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect); return false; } @@ -721,26 +732,6 @@ int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) cons return menuListInternalPadding(style, BottomPadding); } -int RenderThemeChromiumSkia::buttonInternalPaddingLeft() const -{ - return 3; -} - -int RenderThemeChromiumSkia::buttonInternalPaddingRight() const -{ - return 3; -} - -int RenderThemeChromiumSkia::buttonInternalPaddingTop() const -{ - return 1; -} - -int RenderThemeChromiumSkia::buttonInternalPaddingBottom() const -{ - return 1; -} - #if ENABLE(VIDEO) bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e) { diff --git a/WebCore/rendering/RenderThemeChromiumSkia.h b/WebCore/rendering/RenderThemeChromiumSkia.h index 18fa859..dc920b1cf 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/WebCore/rendering/RenderThemeChromiumSkia.h @@ -123,11 +123,6 @@ namespace WebCore { virtual int popupInternalPaddingTop(RenderStyle*) const; virtual int popupInternalPaddingBottom(RenderStyle*) const; - virtual int buttonInternalPaddingLeft() const; - virtual int buttonInternalPaddingRight() const; - virtual int buttonInternalPaddingTop() const; - virtual int buttonInternalPaddingBottom() const; - #if ENABLE(VIDEO) // Media controls virtual bool shouldRenderMediaControlPart(ControlPart, Element*); @@ -153,6 +148,7 @@ namespace WebCore { private: int menuListInternalPadding(RenderStyle*, int paddingType) const; bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*); + IntRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, IntRect partRect, const IntRect& localOffset) const; }; } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h index 3b86980..bbc54a7 100644 --- a/WebCore/rendering/RenderThemeChromiumWin.h +++ b/WebCore/rendering/RenderThemeChromiumWin.h @@ -59,7 +59,7 @@ namespace WebCore { // System fonts. virtual void systemFont(int propId, FontDescription&) const; - virtual Color systemColor(int cssValueId) const;
+ virtual Color systemColor(int cssValueId) const; virtual void adjustSliderThumbSize(RenderObject*) const; diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index 48c6c42..cba927f 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -27,6 +27,8 @@ #import <wtf/HashMap.h> #import <wtf/RetainPtr.h> +class RenderProgress; + #ifdef __OBJC__ @class WebCoreRenderThemeNotificationObserver; #else @@ -78,6 +80,13 @@ public: virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#if ENABLE(PROGRESS_TAG) + // Returns the repeat interval of the animation for the progress bar. + virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const; + // Returns the duration of the animation for the progress bar. + virtual double animationDurationForProgressBar(RenderProgress*) const; +#endif + virtual Color systemColor(int cssValueId) const; protected: @@ -95,6 +104,11 @@ protected: virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; +#if ENABLE(PROGRESS_TAG) + virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#endif + virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index b6ce93d..c0d8020 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -32,6 +32,7 @@ #import "HTMLMediaElement.h" #import "HTMLNames.h" #import "Image.h" +#import "ImageBuffer.h" #import "LocalCurrentGraphicsContext.h" #import "MediaControlElements.h" #import "RenderMedia.h" @@ -39,6 +40,7 @@ #import "RenderView.h" #import "SharedBuffer.h" #import "TimeRanges.h" +#import "ThemeMac.h" #import "WebCoreSystemInterface.h" #import "UserAgentStyleSheets.h" #import <Carbon/Carbon.h> @@ -47,17 +49,26 @@ #import <wtf/StdLibExtras.h> #import <math.h> +#import "RenderProgress.h" + #ifdef BUILDING_ON_TIGER typedef int NSInteger; typedef unsigned NSUInteger; #endif -using std::min; +using namespace std; // The methods in this file are specific to the Mac OS X platform. // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. +// We estimate the animation rate of a Mac OS X progress bar is 33 fps. +// Hard code the value here because we haven't found API for it. +const double progressAnimationFrameRate = 0.033; + +// Mac OS X progress bar animation seems to have 256 frames. +const double progressAnimationNumFrames = 256; + @interface WebCoreRenderThemeNotificationObserver : NSObject { WebCore::RenderTheme *_theme; @@ -735,6 +746,7 @@ const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { + LocalCurrentGraphicsContext localContext(paintInfo.context); setPopupButtonCellState(o, r); NSPopUpButtonCell* popupButton = this->popupButton(); @@ -764,13 +776,64 @@ bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInf paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); } - [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->documentView()]; + [popupButton drawWithFrame:inflatedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; [popupButton setControlView:nil]; paintInfo.context->restore(); return false; } + +#if ENABLE(PROGRESS_TAG) + +double RenderThemeMac::animationRepeatIntervalForProgressBar(RenderProgress*) const +{ + return progressAnimationFrameRate; +} + +double RenderThemeMac::animationDurationForProgressBar(RenderProgress*) const +{ + return progressAnimationNumFrames * progressAnimationFrameRate; +} + +void RenderThemeMac::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const +{ +} + +bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) +{ + RenderProgress* renderProgress = toRenderProgress(renderObject); + HIThemeTrackDrawInfo trackInfo; + trackInfo.version = 0; + trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar; + trackInfo.bounds = IntRect(IntPoint(), rect.size()); + trackInfo.min = 0; + trackInfo.max = numeric_limits<SInt32>::max(); + trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0)); + trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0)); + trackInfo.attributes = kThemeTrackHorizontal; + trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive; + trackInfo.reserved = 0; + trackInfo.filler1 = 0; + + OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(rect.size()); + if (!imageBuffer) + return true; + + HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal); + + paintInfo.context->save(); + + if (renderProgress->style()->direction() == RTL) { + paintInfo.context->translate(2 * rect.x() + rect.width(), 0); + paintInfo.context->scale(FloatSize(-1, 1)); + } + paintInfo.context->drawImage(imageBuffer->image(), DeviceColorSpace, rect.location()); + + paintInfo.context->restore(); + return false; +} +#endif const float baseFontSize = 11.0f; const float baseArrowHeight = 4.0f; @@ -1171,7 +1234,7 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::Paint paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [sliderThumbCell drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; + [sliderThumbCell drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; [sliderThumbCell setControlView:nil]; paintInfo.context->restore(); @@ -1203,7 +1266,7 @@ bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::Paint // Set the search button to nil before drawing. Then reset it so we can draw it later. [search setSearchButtonCell:nil]; - [search drawWithFrame:NSRect(unzoomedRect) inView:o->view()->frameView()->documentView()]; + [search drawWithFrame:NSRect(unzoomedRect) inView:ThemeMac::ensuredView(o->view()->frameView())]; #ifdef BUILDING_ON_TIGER if ([search showsFirstResponder]) wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect)); @@ -1303,7 +1366,7 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderO paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; + [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; [[search cancelButtonCell] setControlView:nil]; paintInfo.context->restore(); @@ -1368,7 +1431,7 @@ bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const Re FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - [[search searchButtonCell] drawWithFrame:localBounds inView:o->view()->frameView()->documentView()]; + [[search searchButtonCell] drawWithFrame:localBounds inView:ThemeMac::ensuredView(o->view()->frameView())]; [[search searchButtonCell] setControlView:nil]; return false; } @@ -1411,7 +1474,7 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search searchButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()]; + [[search searchButtonCell] drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; [[search searchButtonCell] setControlView:nil]; paintInfo.context->restore(); diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index 164a656..75c35ba 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -28,7 +28,6 @@ #include "CSSMutableStyleDeclaration.h" #include "CharacterNames.h" -#include "CString.h" #include "Document.h" #include "Frame.h" #include "FrameView.h" @@ -38,6 +37,7 @@ #include "RenderBR.h" #include "RenderFileUploadControl.h" #include "RenderInline.h" +#include "RenderListItem.h" #include "RenderListMarker.h" #include "RenderPart.h" #include "RenderTableCell.h" @@ -178,10 +178,13 @@ String quoteAndEscapeNonPrintables(const String& s) return String::adopt(result); } -static TextStream &operator<<(TextStream& ts, const RenderObject& o) +static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior) { ts << o.renderName(); + if (behavior & RenderAsTextShowAddresses) + ts << " " << &o; + if (o.style() && o.style()->zIndex()) ts << " zI: " << o.style()->zIndex(); @@ -254,7 +257,7 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o) ts << " [textStrokeWidth=" << o.style()->textStrokeWidth() << "]"; if (!o.isBoxModelObject()) - return ts; + return; const RenderBoxModelObject& box = *toRenderBoxModelObject(&o); if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) { @@ -367,8 +370,6 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o) } } #endif - - return ts; } static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run) @@ -388,7 +389,7 @@ static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBo << "\n"; } -void write(TextStream& ts, const RenderObject& o, int indent) +void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavior behavior) { #if ENABLE(SVG) if (o.isRenderPath()) { @@ -422,7 +423,8 @@ void write(TextStream& ts, const RenderObject& o, int indent) writeIndent(ts, indent); - ts << o << "\n"; + writeRenderObject(ts, o, behavior); + ts << "\n"; if (o.isText() && !o.isBR()) { const RenderText& text = *toRenderText(&o); @@ -435,7 +437,7 @@ void write(TextStream& ts, const RenderObject& o, int indent) for (RenderObject* child = o.firstChild(); child; child = child->nextSibling()) { if (child->hasLayer()) continue; - write(ts, *child, indent + 1); + write(ts, *child, indent + 1, behavior); } if (o.isWidget()) { @@ -447,7 +449,7 @@ void write(TextStream& ts, const RenderObject& o, int indent) view->layout(); RenderLayer* l = root->layer(); if (l) - writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), indent + 1); + writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), indent + 1, behavior); } } } @@ -465,7 +467,12 @@ static void write(TextStream& ts, RenderLayer& l, { writeIndent(ts, indent); - ts << "layer " << layerBounds; + ts << "layer "; + + if (behavior & RenderAsTextShowAddresses) + ts << &l << " "; + + ts << layerBounds; if (!layerBounds.isEmpty()) { if (!backgroundClipRect.contains(layerBounds)) @@ -504,7 +511,7 @@ static void write(TextStream& ts, RenderLayer& l, ts << "\n"; if (paintPhase != LayerPaintPhaseBackground) - write(ts, *l.renderer(), indent + 1); + write(ts, *l.renderer(), indent + 1, behavior); } static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l, @@ -654,4 +661,17 @@ String counterValueForElement(Element* element) return stream.release(); } +String markerTextForListItem(Element* element) +{ + // Make sure the element is not freed during the layout. + RefPtr<Element> elementRef(element); + element->document()->updateLayout(); + + RenderObject* renderer = element->renderer(); + if (!renderer || !renderer->isListItem()) + return String(); + + return toRenderListItem(renderer)->markerText(); +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index 13525e7..4da0bab 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -38,18 +38,21 @@ enum RenderAsTextBehaviorFlags { RenderAsTextBehaviorNormal = 0, RenderAsTextShowAllLayers = 1 << 0, // Dump all layers, not just those that would paint. RenderAsTextShowLayerNesting = 1 << 1, // Annotate the layer lists. - RenderAsTextShowCompositedLayers = 1 << 2 // Show which layers are composited. + RenderAsTextShowCompositedLayers = 1 << 2, // Show which layers are composited. + RenderAsTextShowAddresses = 1 << 3 // Show layer and renderer addresses. }; typedef unsigned RenderAsTextBehavior; String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal); -void write(TextStream&, const RenderObject&, int indent = 0); +void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal); // Helper function shared with SVGRenderTreeAsText String quoteAndEscapeNonPrintables(const String&); String counterValueForElement(Element*); +String markerTextForListItem(Element*); + } // namespace WebCore #endif // RenderTreeAsText_h diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index 13d6f60..ad25c22 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -47,9 +47,6 @@ namespace WebCore { using namespace HTMLNames; -static const int cDefaultWidth = 300; -static const int cDefaultHeight = 150; - RenderVideo::RenderVideo(HTMLVideoElement* video) : RenderMedia(video) { @@ -67,10 +64,10 @@ RenderVideo::RenderVideo(HTMLVideoElement* video) // size since they also have audio thrown at them. By setting the intrinsic // size to 300x1 the video will resize itself in these cases, and audio will // have the correct height (it needs to be > 0 for controls to render properly). - setIntrinsicSize(IntSize(cDefaultWidth, 1)); + setIntrinsicSize(IntSize(defaultSize().width(), 1)); } else - setIntrinsicSize(IntSize(cDefaultWidth, cDefaultHeight)); + setIntrinsicSize(defaultSize()); } } @@ -82,6 +79,15 @@ RenderVideo::~RenderVideo() } } +IntSize RenderVideo::defaultSize() +{ + // These values are specified in the spec. + static const int cDefaultWidth = 300; + static const int cDefaultHeight = 150; + + return IntSize(cDefaultWidth, cDefaultHeight); +} + void RenderVideo::intrinsicSizeChanged() { if (videoElement()->shouldDisplayPosterImage()) diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h index 16c846d..bb2b05c 100644 --- a/WebCore/rendering/RenderVideo.h +++ b/WebCore/rendering/RenderVideo.h @@ -42,7 +42,9 @@ public: void videoSizeChanged(); IntRect videoBox() const; - + + static IntSize defaultSize(); + #if USE(ACCELERATED_COMPOSITING) bool supportsAcceleratedRendering() const; void acceleratedRenderingStateChanged(); diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 094abfd..a95ffdd 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -31,6 +31,7 @@ #include "RenderLayer.h" #include "RenderSelectionInfo.h" #include "RenderWidget.h" +#include "RenderWidgetProtector.h" #include "TransformState.h" #if USE(ACCELERATED_COMPOSITING) @@ -52,6 +53,10 @@ RenderView::RenderView(Node* node, FrameView* view) , m_selectionEndPos(-1) , m_printImages(true) , m_maximalOutlineSize(0) + , m_bestTruncatedAt(0) + , m_truncatorWidth(0) + , m_minimumColumnHeight(0) + , m_forcedPageBreak(false) , m_layoutState(0) , m_layoutStateDisableCount(0) { @@ -577,9 +582,29 @@ bool RenderView::printing() const void RenderView::updateWidgetPositions() { - RenderWidgetSet::iterator end = m_widgets.end(); - for (RenderWidgetSet::iterator it = m_widgets.begin(); it != end; ++it) - (*it)->updateWidgetPosition(); + // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running + // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets + // alive during enumeration. + + size_t size = m_widgets.size(); + + Vector<RenderWidget*> renderWidgets; + renderWidgets.reserveCapacity(size); + + RenderWidgetSet::const_iterator end = m_widgets.end(); + for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) { + renderWidgets.uncheckedAppend(*it); + (*it)->ref(); + } + + for (size_t i = 0; i < size; ++i) + renderWidgets[i]->updateWidgetPosition(); + + for (size_t i = 0; i < size; ++i) + renderWidgets[i]->widgetPositionsUpdated(); + + for (size_t i = 0; i < size; ++i) + renderWidgets[i]->deref(renderArena()); } void RenderView::addWidget(RenderWidget* o) @@ -722,6 +747,16 @@ bool RenderView::usesCompositing() const return m_compositor && m_compositor->inCompositingMode(); } +void RenderView::compositingStateChanged(bool) +{ + Element* elt = document()->ownerElement(); + if (!elt) + return; + + // Trigger a recalcStyle in the parent document, to update compositing in that document. + elt->setNeedsStyleRecalc(SyntheticStyleChange); +} + RenderLayerCompositor* RenderView::compositor() { if (!m_compositor) diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index faa2465..fb68da3 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -166,6 +166,7 @@ public: #if USE(ACCELERATED_COMPOSITING) RenderLayerCompositor* compositor(); bool usesCompositing() const; + void compositingStateChanged(bool nowComposited); #endif protected: diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index f6f6da8..b03dcd6 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * Copyright (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -151,13 +151,22 @@ RenderWidget::~RenderWidget() bool RenderWidget::setWidgetGeometry(const IntRect& frame) { ASSERT(!widgetHierarchyUpdateSuspendCount); - if (!node() || m_widget->frameRect() == frame) + if (!node()) return false; + IntRect clipRect = enclosingLayer()->childrenClipRect(); + bool clipChanged = m_clipRect != clipRect; + bool boundsChanged = m_widget->frameRect() != frame; + + if (!boundsChanged && !clipChanged) + return false; + + m_clipRect = clipRect; + RenderWidgetProtector protector(this); RefPtr<Node> protectedNode(node()); m_widget->setFrameRect(frame); - return true; + return boundsChanged; } void RenderWidget::setWidget(PassRefPtr<Widget> widget) @@ -304,7 +313,7 @@ void RenderWidget::deref(RenderArena *arena) void RenderWidget::updateWidgetPosition() { - if (!m_widget) + if (!m_widget || !node()) // Check the node in case destroy() has been called. return; // FIXME: This doesn't work correctly with transforms. @@ -327,6 +336,21 @@ void RenderWidget::updateWidgetPosition() #endif } +void RenderWidget::widgetPositionsUpdated() +{ + if (!m_widget) + return; + m_widget->widgetPositionsUpdated(); +} + +IntRect RenderWidget::windowClipRect() const +{ + if (!m_frameView) + return IntRect(); + + return intersection(m_frameView->contentsToWindow(m_clipRect), m_frameView->windowClipRect()); +} + void RenderWidget::setSelectionState(SelectionState state) { if (selectionState() != state) { diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h index 6cad04a..b85b951 100644 --- a/WebCore/rendering/RenderWidget.h +++ b/WebCore/rendering/RenderWidget.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -39,12 +39,17 @@ public: static RenderWidget* find(const Widget*); void updateWidgetPosition(); + void widgetPositionsUpdated(); + IntRect windowClipRect() const; void showSubstituteImage(PassRefPtr<Image>); static void suspendWidgetHierarchyUpdates(); static void resumeWidgetHierarchyUpdates(); + RenderArena* ref() { ++m_refCount; return renderArena(); } + void deref(RenderArena*); + protected: RenderWidget(Node*); @@ -54,11 +59,11 @@ protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual void layout(); + virtual void paint(PaintInfo&, int x, int y); private: virtual bool isWidget() const { return true; } - virtual void paint(PaintInfo&, int x, int y); virtual void destroy(); virtual void setSelectionState(SelectionState); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); @@ -66,13 +71,10 @@ private: bool setWidgetGeometry(const IntRect&); - friend class RenderWidgetProtector; - RenderArena* ref() { ++m_refCount; return renderArena(); } - void deref(RenderArena*); - RefPtr<Widget> m_widget; RefPtr<Image> m_substituteImage; FrameView* m_frameView; + IntRect m_clipRect; // The rectangle needs to remain correct after scrolling, so it is stored in content view coordinates, and not clipped to window. int m_refCount; }; diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index 7fce1d3..fae0cba 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -49,8 +49,8 @@ public: void detachEllipsisBox(RenderArena*); - RootInlineBox* nextRootBox() const { return static_cast<RootInlineBox*>(m_nextLine); } - RootInlineBox* prevRootBox() const { return static_cast<RootInlineBox*>(m_prevLine); } + RootInlineBox* nextRootBox() const { return static_cast<RootInlineBox*>(m_nextLineBox); } + RootInlineBox* prevRootBox() const { return static_cast<RootInlineBox*>(m_prevLineBox); } virtual void adjustPosition(int dx, int dy); diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index 65aa5a1..bda512f 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -405,12 +405,11 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t if (isGlyphPhase || isSelectionGlyphPhase) { // Set a text shadow if we have one. - // FIXME: Support multiple shadow effects. Need more from the CG API before - // we can do this. + // FIXME: Support multiple shadow effects. See how it's done in InlineTextBox.cpp. bool setShadow = false; if (styleToUse->textShadow()) { - paintInfo.context->setShadow(IntSize(styleToUse->textShadow()->x, styleToUse->textShadow()->y), - styleToUse->textShadow()->blur, styleToUse->textShadow()->color, + paintInfo.context->setShadow(IntSize(styleToUse->textShadow()->x(), styleToUse->textShadow()->y()), + styleToUse->textShadow()->blur(), styleToUse->textShadow()->color(), styleToUse->colorSpace()); setShadow = true; } diff --git a/WebCore/rendering/SVGMarkerData.h b/WebCore/rendering/SVGMarkerData.h index 5ff2993..ba11e7e 100644 --- a/WebCore/rendering/SVGMarkerData.h +++ b/WebCore/rendering/SVGMarkerData.h @@ -27,7 +27,7 @@ namespace WebCore { -class SVGResourceMarker; +class RenderSVGResourceMarker; class SVGMarkerData { public: @@ -38,14 +38,14 @@ public: End }; - SVGMarkerData(const Type& type = Unknown, SVGResourceMarker* marker = 0) + SVGMarkerData(const Type& type = Unknown, RenderSVGResourceMarker* marker = 0) : m_type(type) , m_marker(marker) { } FloatPoint origin() const { return m_origin; } - SVGResourceMarker* marker() const { return m_marker; } + RenderSVGResourceMarker* marker() const { return m_marker; } float currentAngle() const { @@ -74,7 +74,7 @@ public: return narrowPrecisionToFloat(angle); } - void updateTypeAndMarker(const Type& type, SVGResourceMarker* marker) + void updateTypeAndMarker(const Type& type, RenderSVGResourceMarker* marker) { m_type = type; m_marker = marker; @@ -121,7 +121,7 @@ private: } Type m_type; - SVGResourceMarker* m_marker; + RenderSVGResourceMarker* m_marker; FloatPoint m_origin; FloatPoint m_subpathStart; FloatPoint m_inslopePoints[2]; diff --git a/WebCore/rendering/SVGMarkerLayoutInfo.cpp b/WebCore/rendering/SVGMarkerLayoutInfo.cpp index 3fe513f..b771cf8 100644 --- a/WebCore/rendering/SVGMarkerLayoutInfo.cpp +++ b/WebCore/rendering/SVGMarkerLayoutInfo.cpp @@ -26,8 +26,7 @@ #if ENABLE(SVG) #include "SVGMarkerLayoutInfo.h" -#include "RenderSVGViewportContainer.h" -#include "SVGResourceMarker.h" +#include "RenderSVGResourceMarker.h" namespace WebCore { @@ -52,7 +51,7 @@ static inline void processStartAndMidMarkers(void* infoPtr, const PathElement* e markerData.updateOutslope(element->points[0]); // Draw the marker for the previous element - SVGResourceMarker* marker = markerData.marker(); + RenderSVGResourceMarker* marker = markerData.marker(); if (elementIndex > 0 && marker) info.addLayoutedMarker(marker, markerData.origin(), markerData.currentAngle()); @@ -66,7 +65,7 @@ static inline void processStartAndMidMarkers(void* infoPtr, const PathElement* e ++elementIndex; } -FloatRect SVGMarkerLayoutInfo::calculateBoundaries(SVGResourceMarker* startMarker, SVGResourceMarker* midMarker, SVGResourceMarker* endMarker, float strokeWidth, const Path& path) +FloatRect SVGMarkerLayoutInfo::calculateBoundaries(RenderSVGResourceMarker* startMarker, RenderSVGResourceMarker* midMarker, RenderSVGResourceMarker* endMarker, float strokeWidth, const Path& path) { m_layout.clear(); m_midMarker = midMarker; @@ -90,7 +89,7 @@ FloatRect SVGMarkerLayoutInfo::calculateBoundaries(SVGResourceMarker* startMarke for (; it != end; ++it) { MarkerLayout& layout = *it; - RenderSVGViewportContainer* markerContent = layout.marker->renderer(); + RenderSVGResourceMarker* markerContent = layout.marker; ASSERT(markerContent); bounds.unite(markerContent->markerBoundaries(layout.matrix)); @@ -113,7 +112,7 @@ void SVGMarkerLayoutInfo::drawMarkers(RenderObject::PaintInfo& paintInfo) } } -void SVGMarkerLayoutInfo::addLayoutedMarker(SVGResourceMarker* marker, const FloatPoint& origin, float angle) +void SVGMarkerLayoutInfo::addLayoutedMarker(RenderSVGResourceMarker* marker, const FloatPoint& origin, float angle) { ASSERT(marker); m_layout.append(MarkerLayout(marker, marker->markerTransformation(origin, angle, m_strokeWidth))); diff --git a/WebCore/rendering/SVGMarkerLayoutInfo.h b/WebCore/rendering/SVGMarkerLayoutInfo.h index 517c993..6011a2d 100644 --- a/WebCore/rendering/SVGMarkerLayoutInfo.h +++ b/WebCore/rendering/SVGMarkerLayoutInfo.h @@ -28,17 +28,17 @@ namespace WebCore { class Path; -class SVGResourceMarker; +class RenderSVGResourceMarker; struct MarkerLayout { - MarkerLayout(SVGResourceMarker* markerObj = 0, AffineTransform matrixObj = AffineTransform()) + MarkerLayout(RenderSVGResourceMarker* markerObj = 0, AffineTransform matrixObj = AffineTransform()) : marker(markerObj) , matrix(matrixObj) { ASSERT(marker); } - SVGResourceMarker* marker; + RenderSVGResourceMarker* marker; AffineTransform matrix; }; @@ -47,17 +47,17 @@ public: SVGMarkerLayoutInfo(); ~SVGMarkerLayoutInfo(); - FloatRect calculateBoundaries(SVGResourceMarker* startMarker, SVGResourceMarker* midMarker, SVGResourceMarker* endMarker, float strokeWidth, const Path&); + FloatRect calculateBoundaries(RenderSVGResourceMarker* startMarker, RenderSVGResourceMarker* midMarker, RenderSVGResourceMarker* endMarker, float strokeWidth, const Path&); void drawMarkers(RenderObject::PaintInfo&); // Used by static inline helper functions in SVGMarkerLayoutInfo.cpp SVGMarkerData& markerData() { return m_markerData; } - SVGResourceMarker* midMarker() const { return m_midMarker; } + RenderSVGResourceMarker* midMarker() const { return m_midMarker; } int& elementIndex() { return m_elementIndex; } - void addLayoutedMarker(SVGResourceMarker*, const FloatPoint& origin, float angle); + void addLayoutedMarker(RenderSVGResourceMarker*, const FloatPoint& origin, float angle); private: - SVGResourceMarker* m_midMarker; + RenderSVGResourceMarker* m_midMarker; // Used while layouting markers int m_elementIndex; @@ -70,5 +70,5 @@ private: } -#endif // ENABLE(SVG) -#endif // SVGMarkerLayoutInfo_h +#endif +#endif diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index dc1b3c1..dd67746 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -4,6 +4,7 @@ * (C) 2007 Eric Seidel <eric@webkit.org> * (C) 2009 Google, Inc. All rights reserved. * (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -33,10 +34,11 @@ #include "RenderObject.h" #include "RenderSVGContainer.h" #include "RenderSVGResource.h" +#include "RenderSVGResourceClipper.h" +#include "RenderSVGResourceFilter.h" +#include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" #include "RenderView.h" -#include "SVGResourceClipper.h" -#include "SVGResourceFilter.h" #include "SVGStyledElement.h" #include "SVGURIReference.h" #include "TransformState.h" @@ -78,7 +80,7 @@ void SVGRenderBase::mapLocalToContainer(const RenderObject* object, RenderBoxMod object->parent()->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); } -bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter) +bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& repaintRect, RenderSVGResourceFilter*& filter, RenderSVGResourceFilter* rootFilter) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); @@ -103,23 +105,23 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject paintInfo.context->beginTransparencyLayer(opacity); } - if (ShadowData* shadow = svgStyle->shadow()) { + if (const ShadowData* shadow = svgStyle->shadow()) { paintInfo.context->clip(repaintRect); - paintInfo.context->setShadow(IntSize(shadow->x, shadow->y), shadow->blur, shadow->color, style->colorSpace()); + paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace()); paintInfo.context->beginTransparencyLayer(1.0f); } #if ENABLE(FILTERS) - AtomicString filterId(svgStyle->filter()); + AtomicString filterId(svgStyle->filterResource()); #endif - AtomicString clipperId(svgStyle->clipPath()); - AtomicString maskerId(svgStyle->maskElement()); + AtomicString clipperId(svgStyle->clipperResource()); + AtomicString maskerId(svgStyle->maskerResource()); Document* document = object->document(); #if ENABLE(FILTERS) - SVGResourceFilter* newFilter = getFilterById(document, filterId, object); + RenderSVGResourceFilter* newFilter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId); if (newFilter == rootFilter) { // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. // The filter is NOT meant to be applied twice in that case! @@ -129,23 +131,20 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject filter = newFilter; #endif - // apply Masker if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { if (!masker->applyResource(object, paintInfo.context)) return false; } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); - if (SVGResourceClipper* clipper = getClipperById(document, clipperId, object)) { - clipper->addClient(styledElement); - clipper->applyClip(paintInfo.context, object->objectBoundingBox()); - } else if (!clipperId.isEmpty()) + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) + clipper->applyResource(object, paintInfo.context); + else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); #if ENABLE(FILTERS) if (filter) { - filter->addClient(styledElement); - if (!filter->prepareFilter(paintInfo.context, object)) + if (!filter->applyResource(object, paintInfo.context)) return false; } else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); @@ -154,7 +153,7 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject return true; } -void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, SVGResourceFilter*& filter, GraphicsContext* savedContext) +void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, RenderSVGResourceFilter*& filter, GraphicsContext* savedContext) { #if !ENABLE(FILTERS) UNUSED_PARAM(filter); @@ -168,7 +167,7 @@ void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::P #if ENABLE(FILTERS) if (filter) { - filter->applyFilter(paintInfo.context, object); + filter->postApplyResource(object, paintInfo.context); paintInfo.context = savedContext; } #endif @@ -188,7 +187,14 @@ void renderSubtreeToImage(ImageBuffer* image, RenderObject* item) ASSERT(item); ASSERT(image); ASSERT(image->context()); - RenderObject::PaintInfo info(image->context(), IntRect(), PaintPhaseForeground, 0, 0, 0); + + // FIXME: This sets the rect to the viewable area of the current frame. This + // is used to support text drawings to the ImageBuffer. See bug 30399. + IntRect rect; + FrameView* frameView = item->document()->view(); + if (frameView) + rect = IntRect(0, 0, frameView->visibleWidth(), frameView->visibleHeight()); + RenderObject::PaintInfo info(image->context(), rect, 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. @@ -276,9 +282,8 @@ bool SVGRenderBase::isOverflowHidden(const RenderObject* object) FloatRect SVGRenderBase::filterBoundingBoxForRenderer(const RenderObject* object) const { #if ENABLE(FILTERS) - SVGResourceFilter* filter = getFilterById(object->document(), object->style()->svgStyle()->filter(), object); - if (filter) - return filter->filterBoundingBox(object->objectBoundingBox()); + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), object->style()->svgStyle()->filterResource())) + return filter->resourceBoundingBox(object->objectBoundingBox()); #else UNUSED_PARAM(object); #endif @@ -287,26 +292,37 @@ FloatRect SVGRenderBase::filterBoundingBoxForRenderer(const RenderObject* object FloatRect SVGRenderBase::clipperBoundingBoxForRenderer(const RenderObject* object) const { - SVGResourceClipper* clipper = getClipperById(object->document(), object->style()->svgStyle()->clipPath(), object); - if (clipper) - return clipper->clipperBoundingBox(object->objectBoundingBox()); + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), object->style()->svgStyle()->clipperResource())) + return clipper->resourceBoundingBox(object->objectBoundingBox()); return FloatRect(); } FloatRect SVGRenderBase::maskerBoundingBoxForRenderer(const RenderObject* object) const { - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskerResource())) return masker->resourceBoundingBox(object->objectBoundingBox()); return FloatRect(); } -void SVGRenderBase::deregisterFromResources(RenderObject* object) +void deregisterFromResources(RenderObject* object) { - // We only have a renderer for masker at the moment. - if (RenderSVGResourceMasker* resource = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) - resource->invalidateClient(object); + // We only have the renderer for masker and clipper at the moment. + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskerResource())) + masker->invalidateClient(object); + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), object->style()->svgStyle()->clipperResource())) + clipper->invalidateClient(object); +#if ENABLE(FILTERS) + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), object->style()->svgStyle()->filterResource())) + filter->invalidateClient(object); +#endif + if (RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerStartResource())) + startMarker->invalidateClient(object); + if (RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerMidResource())) + midMarker->invalidateClient(object); + if (RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerEndResource())) + endMarker->invalidateClient(object); } void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineTransform& localToAncestorTransform) @@ -318,6 +334,16 @@ void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineT paintInfo.rect = localToAncestorTransform.inverse().mapRect(paintInfo.rect); } -} // namespace WebCore +const RenderObject* findTextRootObject(const RenderObject* start) +{ + while (start && !start->isSVGText()) + start = start->parent(); + ASSERT(start); + ASSERT(start->isSVGText()); -#endif // ENABLE(SVG) + return start; +} + +} + +#endif diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index 427ff1f..4b59b71 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -31,7 +31,7 @@ namespace WebCore { -class SVGResourceFilter; +class RenderSVGResourceFilter; class ImageBuffer; // SVGRendererBase is an abstract base class which all SVG renderers inherit @@ -47,8 +47,8 @@ public: // FIXME: These are only public for SVGRootInlineBox. // It's unclear if these should be exposed or not. SVGRootInlineBox may // pass the wrong RenderObject* and boundingBox to these functions. - static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0); - static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext); + static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, RenderSVGResourceFilter*&, RenderSVGResourceFilter* rootFilter = 0); + static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, RenderSVGResourceFilter*&, GraphicsContext* savedContext); // Layout all children of the passed render object static void layoutChildren(RenderObject*, bool selfNeedsLayout); @@ -73,8 +73,6 @@ protected: // Used to share the "walk all the children" logic between objectBoundingBox // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent); - - static void deregisterFromResources(RenderObject*); }; // FIXME: This should move to RenderObject or PaintInfo @@ -84,7 +82,10 @@ void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. void renderSubtreeToImage(ImageBuffer*, RenderObject*); +void deregisterFromResources(RenderObject*); void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); + +const RenderObject* findTextRootObject(const RenderObject* start); } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index f892144..0f1f15d 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2004, 2005, 2007, 2009 Apple Inc. All rights reserved. * (C) 2005 Rob Buis <buis@kde.org> * (C) 2006 Alexander Kellett <lypanov@kde.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,10 +35,14 @@ #include "HTMLNames.h" #include "InlineTextBox.h" #include "NodeRenderStyle.h" +#include "Path.h" #include "RenderImage.h" #include "RenderPath.h" #include "RenderSVGContainer.h" #include "RenderSVGInlineText.h" +#include "RenderSVGResourceClipper.h" +#include "RenderSVGResourceFilter.h" +#include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" #include "RenderSVGRoot.h" #include "RenderSVGText.h" @@ -47,7 +52,6 @@ #include "SVGPaintServerGradient.h" #include "SVGPaintServerPattern.h" #include "SVGPaintServerSolid.h" -#include "SVGResourceClipper.h" #include "SVGRootInlineBox.h" #include "SVGStyledElement.h" #include <math.h> @@ -196,6 +200,20 @@ TextStream& operator<<(TextStream& ts, const AffineTransform& transform) return ts; } +static TextStream& operator<<(TextStream& ts, const WindRule rule) +{ + switch (rule) { + case RULE_NONZERO: + ts << "NON-ZERO"; + break; + case RULE_EVENODD: + ts << "EVEN-ODD"; + break; + } + + return ts; +} + static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType) { switch (unitType) { @@ -213,6 +231,23 @@ static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& u return ts; } +static TextStream& operator<<(TextStream& ts, const SVGMarkerElement::SVGMarkerUnitsType& markerUnit) +{ + switch (markerUnit) { + case SVGMarkerElement::SVG_MARKERUNITS_UNKNOWN: + ts << "unknown"; + break; + case SVGMarkerElement::SVG_MARKERUNITS_USERSPACEONUSE: + ts << "userSpaceOnUse"; + break; + case SVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH: + ts << "strokeWidth"; + break; + } + + return ts; +} + TextStream& operator<<(TextStream& ts, const Color& c) { return ts << c.name(); @@ -316,14 +351,12 @@ static void writeStyle(TextStream& ts, const RenderObject& object) writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO); ts << "}]"; } + writeIfNotDefault(ts, "clip rule", svgStyle->clipRule(), RULE_NONZERO); } - if (!svgStyle->clipPath().isEmpty()) - writeNameAndQuotedValue(ts, "clip path", svgStyle->clipPath()); - writeIfNotEmpty(ts, "start marker", svgStyle->startMarker()); - writeIfNotEmpty(ts, "middle marker", svgStyle->midMarker()); - writeIfNotEmpty(ts, "end marker", svgStyle->endMarker()); - writeIfNotEmpty(ts, "filter", svgStyle->filter()); + writeIfNotEmpty(ts, "start marker", svgStyle->markerStartResource()); + writeIfNotEmpty(ts, "middle marker", svgStyle->markerMidResource()); + writeIfNotEmpty(ts, "end marker", svgStyle->markerEndResource()); } static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object) @@ -496,9 +529,49 @@ void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) ASSERT(masker); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); +#if ENABLE(FILTERS) + } else if (resource->resourceType() == FilterResourceType) { + RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource); + ASSERT(filter); + writeNameValuePair(ts, "filterUnits", filter->filterUnits()); + writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); + if (OwnPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) { + ts << "\n"; + const HashMap<AtomicString, RefPtr<FilterEffect> >& effects = builder->namedEffects(); + HashMap<AtomicString, RefPtr<FilterEffect> >::const_iterator end = effects.end(); + for (HashMap<AtomicString, RefPtr<FilterEffect> >::const_iterator it = effects.begin(); it != end; ++it) { + writeIndent(ts, indent); + ts << " [primitve=\"" << it->first << "\" "; + it->second->externalRepresentation(ts); + ts << "]\n"; + } + writeIndent(ts, indent); + // FIXME: Some effects don't give a representation back. So we miss some more informations + // after '[last primitive' . + // We also just dump named effects and the last effect at the moment, more effects + // without a name might be in the pipe. + ts << " [last primitive "; + if (FilterEffect* lastEffect = builder->lastEffect()) + lastEffect->externalRepresentation(ts); + ts << "]"; + } +#endif + } else if (resource->resourceType() == ClipperResourceType) { + RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); + ASSERT(clipper); + writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); + } else if (resource->resourceType() == MarkerResourceType) { + RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource); + ASSERT(marker); + writeNameValuePair(ts, "markerUnits", marker->markerUnits()); + ts << " [ref at " << marker->referencePoint() << "]"; + ts << " [angle="; + if (marker->angle() == -1) + ts << "auto" << "]"; + else + ts << marker->angle() << "]"; } - // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. ts << "\n"; writeChildren(ts, object, indent); } @@ -558,17 +631,38 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) const RenderStyle* style = object.style(); const SVGRenderStyle* svgStyle = style->svgStyle(); - if (!svgStyle->maskElement().isEmpty()) { - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskElement())) { + if (!svgStyle->maskerResource().isEmpty()) { + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskerResource())) { writeIndent(ts, indent); ts << " "; - writeNameAndQuotedValue(ts, "masker", svgStyle->maskElement()); + writeNameAndQuotedValue(ts, "masker", svgStyle->maskerResource()); ts << " "; writeStandardPrefix(ts, *masker, 0); ts << " " << masker->resourceBoundingBox(object.objectBoundingBox()) << "\n"; } } - // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. + if (!svgStyle->clipperResource().isEmpty()) { + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object.document(), svgStyle->clipperResource())) { + writeIndent(ts, indent); + ts << " "; + writeNameAndQuotedValue(ts, "clipPath", svgStyle->clipperResource()); + ts << " "; + writeStandardPrefix(ts, *clipper, 0); + ts << " " << clipper->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + } + } +#if ENABLE(FILTERS) + if (!svgStyle->filterResource().isEmpty()) { + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object.document(), svgStyle->filterResource())) { + writeIndent(ts, indent); + ts << " "; + writeNameAndQuotedValue(ts, "filter", svgStyle->filterResource()); + ts << " "; + writeStandardPrefix(ts, *filter, 0); + ts << " " << filter->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + } + } +#endif } void writeRenderResources(TextStream& ts, Node* parent) @@ -592,8 +686,7 @@ void writeRenderResources(TextStream& ts, Node* parent) if (resource->isPaintServer()) { RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource); ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n"; - } else - ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n"; + } } while ((node = node->traverseNextNode(parent))); } diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index 03b9db4..89b4375 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -28,9 +28,11 @@ #include "SVGRootInlineBox.h" #include "Editor.h" +#include "FloatConversion.h" #include "Frame.h" #include "GraphicsContext.h" #include "RenderBlock.h" +#include "RenderSVGResourceFilter.h" #include "RenderSVGRoot.h" #include "SVGInlineFlowBox.h" #include "SVGInlineTextBox.h" @@ -38,7 +40,6 @@ #include "SVGPaintServer.h" #include "SVGRenderStyleDefs.h" #include "SVGRenderSupport.h" -#include "SVGResourceFilter.h" #include "SVGTextPositioningElement.h" #include "SVGURIReference.h" #include "Text.h" @@ -336,7 +337,7 @@ static float calculateKerning(RenderObject* item) // Helper class for paint() struct SVGRootInlineBoxPaintWalker { - SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, SVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty) + SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, RenderSVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty) : m_rootBox(rootBox) , m_chunkStarted(false) , m_paintInfo(paintInfo) @@ -668,8 +669,8 @@ private: RenderObject::PaintInfo m_savedInfo; FloatRect m_boundingBox; - SVGResourceFilter* m_filter; - SVGResourceFilter* m_rootFilter; + RenderSVGResourceFilter* m_filter; + RenderSVGResourceFilter* m_rootFilter; SVGPaintServer* m_fillPaintServer; SVGPaintServer* m_strokePaintServer; @@ -691,7 +692,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) RenderObject::PaintInfo savedInfo(paintInfo); paintInfo.context->save(); - SVGResourceFilter* filter = 0; + RenderSVGResourceFilter* filter = 0; FloatRect boundingBox(tx + x(), ty + y(), width(), height()); // Initialize text rendering @@ -1413,7 +1414,7 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& } } - double kerning = 0.0; + float kerning = 0.0f; #if ENABLE(SVG_FONTS) SVGFontElement* svgFont = 0; if (style->font().isSVGFont()) @@ -1422,25 +1423,26 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& if (lastGlyph.isValid && style->font().isSVGFont()) { SVGHorizontalKerningPair kerningPair; if (svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeStr, glyphName, kerningPair)) - kerning = kerningPair.kerning; + kerning = narrowPrecisionToFloat(kerningPair.kerning); } if (style->font().isSVGFont()) { lastGlyph.unicode = unicodeStr; lastGlyph.glyphName = glyphName; lastGlyph.isValid = true; + kerning *= style->font().size() / style->font().primaryFont()->unitsPerEm(); } else lastGlyph.isValid = false; #endif - svgChar.x -= (float)kerning; + svgChar.x -= kerning; // Advance to new position if (isVerticalText) { svgChar.drawnSeperated = true; info.cury += glyphAdvance + spacing; } else - info.curx += glyphAdvance + spacing - (float)kerning; + info.curx += glyphAdvance + spacing - kerning; // Advance to next character group for (int k = 0; k < charsConsumed; ++k) { diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index fc7f7f0..4cd55c5 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -63,18 +63,17 @@ bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, Hit VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& point) { - int contentsX = point.x(); - int contentsY = point.y(); + IntPoint contentsPoint(point); // Multiline text controls have the scroll on shadowAncestorNode, so we need to take that // into account here. if (m_multiLine) { RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer()); if (renderer->hasOverflowClip()) - renderer->layer()->addScrolledContentOffset(contentsX, contentsY); + contentsPoint += renderer->layer()->scrolledContentOffset(); } - return RenderBlock::positionForPoint(IntPoint(contentsX, contentsY)); + return RenderBlock::positionForPoint(contentsPoint); } TextControlInnerElement::TextControlInnerElement(Document* doc, Node* shadowParent) diff --git a/WebCore/rendering/style/BorderData.h b/WebCore/rendering/style/BorderData.h index 8ca0d65..96caf97 100644 --- a/WebCore/rendering/style/BorderData.h +++ b/WebCore/rendering/style/BorderData.h @@ -32,76 +32,90 @@ namespace WebCore { class BorderData { +friend class RenderStyle; public: - BorderValue left; - BorderValue right; - BorderValue top; - BorderValue bottom; - - NinePieceImage image; - - IntSize topLeft; - IntSize topRight; - IntSize bottomLeft; - IntSize bottomRight; - bool hasBorder() const { - bool haveImage = image.hasImage(); - return left.nonZero(!haveImage) || right.nonZero(!haveImage) || top.nonZero(!haveImage) || bottom.nonZero(!haveImage); + bool haveImage = m_image.hasImage(); + return m_left.nonZero(!haveImage) || m_right.nonZero(!haveImage) || m_top.nonZero(!haveImage) || m_bottom.nonZero(!haveImage); } bool hasBorderRadius() const { - if (topLeft.width() > 0) + if (m_topLeft.width() > 0) return true; - if (topRight.width() > 0) + if (m_topRight.width() > 0) return true; - if (bottomLeft.width() > 0) + if (m_bottomLeft.width() > 0) return true; - if (bottomRight.width() > 0) + if (m_bottomRight.width() > 0) return true; return false; } unsigned short borderLeftWidth() const { - if (!image.hasImage() && (left.style() == BNONE || left.style() == BHIDDEN)) + if (!m_image.hasImage() && (m_left.style() == BNONE || m_left.style() == BHIDDEN)) return 0; - return left.width; + return m_left.width(); } unsigned short borderRightWidth() const { - if (!image.hasImage() && (right.style() == BNONE || right.style() == BHIDDEN)) + if (!m_image.hasImage() && (m_right.style() == BNONE || m_right.style() == BHIDDEN)) return 0; - return right.width; + return m_right.width(); } unsigned short borderTopWidth() const { - if (!image.hasImage() && (top.style() == BNONE || top.style() == BHIDDEN)) + if (!m_image.hasImage() && (m_top.style() == BNONE || m_top.style() == BHIDDEN)) return 0; - return top.width; + return m_top.width(); } unsigned short borderBottomWidth() const { - if (!image.hasImage() && (bottom.style() == BNONE || bottom.style() == BHIDDEN)) + if (!m_image.hasImage() && (m_bottom.style() == BNONE || m_bottom.style() == BHIDDEN)) return 0; - return bottom.width; + return m_bottom.width(); } bool operator==(const BorderData& o) const { - return left == o.left && right == o.right && top == o.top && bottom == o.bottom && image == o.image && - topLeft == o.topLeft && topRight == o.topRight && bottomLeft == o.bottomLeft && bottomRight == o.bottomRight; + return m_left == o.m_left && m_right == o.m_right && m_top == o.m_top && m_bottom == o.m_bottom && m_image == o.m_image + && m_topLeft == o.m_topLeft && m_topRight == o.m_topRight && m_bottomLeft == o.m_bottomLeft && m_bottomRight == o.m_bottomRight; } bool operator!=(const BorderData& o) const { return !(*this == o); } + + const BorderValue& left() const { return m_left; } + const BorderValue& right() const { return m_right; } + const BorderValue& top() const { return m_top; } + const BorderValue& bottom() const { return m_bottom; } + + const NinePieceImage& image() const { return m_image; } + + const IntSize& topLeft() const { return m_topLeft; } + const IntSize& topRight() const { return m_topRight; } + const IntSize& bottomLeft() const { return m_bottomLeft; } + const IntSize& bottomRight() const { return m_bottomRight; } + +private: + BorderValue m_left; + BorderValue m_right; + BorderValue m_top; + BorderValue m_bottom; + + NinePieceImage m_image; + + IntSize m_topLeft; + IntSize m_topRight; + IntSize m_bottomLeft; + IntSize m_bottomRight; }; } // namespace WebCore diff --git a/WebCore/rendering/style/BorderValue.h b/WebCore/rendering/style/BorderValue.h index e61e708..3e6fd5d 100644 --- a/WebCore/rendering/style/BorderValue.h +++ b/WebCore/rendering/style/BorderValue.h @@ -31,27 +31,22 @@ namespace WebCore { class BorderValue { +friend class RenderStyle; public: BorderValue() - : width(3) + : m_width(3) , m_style(BNONE) { } - Color color; - unsigned width : 12; - unsigned m_style : 4; // EBorderStyle - - EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); } - bool nonZero(bool checkStyle = true) const { - return width != 0 && (!checkStyle || m_style != BNONE); + return width() && (!checkStyle || m_style != BNONE); } bool isTransparent() const { - return color.isValid() && color.alpha() == 0; + return m_color.isValid() && !m_color.alpha(); } bool isVisible(bool checkStyle = true) const @@ -61,13 +56,22 @@ public: bool operator==(const BorderValue& o) const { - return width == o.width && m_style == o.m_style && color == o.color; + return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color; } bool operator!=(const BorderValue& o) const { return !(*this == o); } + + const Color& color() const { return m_color; } + unsigned short width() const { return m_width; } + EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); } + +protected: + Color m_color; + unsigned m_width : 12; + unsigned m_style : 4; // EBorderStyle }; } // namespace WebCore diff --git a/WebCore/rendering/style/CollapsedBorderValue.h b/WebCore/rendering/style/CollapsedBorderValue.h index 805f474..6207231 100644 --- a/WebCore/rendering/style/CollapsedBorderValue.h +++ b/WebCore/rendering/style/CollapsedBorderValue.h @@ -29,36 +29,42 @@ namespace WebCore { -struct CollapsedBorderValue { +class CollapsedBorderValue { +friend class RenderStyle; +public: CollapsedBorderValue() - : border(0) - , precedence(BOFF) + : m_border(0) + , m_precedence(BOFF) { } - CollapsedBorderValue(const BorderValue* b, EBorderPrecedence p) - : border(b) - , precedence(p) + CollapsedBorderValue(const BorderValue* b, Color c, EBorderPrecedence p) + : m_border(b) + , m_borderColor(c) + , m_precedence(p) { } - int width() const { return border && border->nonZero() ? border->width : 0; } - EBorderStyle style() const { return border ? border->style() : BHIDDEN; } - bool exists() const { return border; } - Color color() const { return border ? border->color : Color(); } - bool isTransparent() const { return border ? border->isTransparent() : true; } - + int width() const { return m_border && m_border->nonZero() ? m_border->width() : 0; } + EBorderStyle style() const { return m_border ? m_border->style() : BHIDDEN; } + bool exists() const { return m_border; } + const Color& color() const { return m_borderColor; } + bool isTransparent() const { return m_border ? m_border->isTransparent() : true; } + EBorderPrecedence precedence() const { return m_precedence; } + bool operator==(const CollapsedBorderValue& o) const { - if (!border) - return !o.border; - if (!o.border) + if (!m_border) + return !o.m_border; + if (!o.m_border) return false; - return *border == *o.border && precedence == o.precedence; + return *m_border == *o.m_border && m_borderColor == o.m_borderColor && m_precedence == o.m_precedence; } - - const BorderValue* border; - EBorderPrecedence precedence; + +private: + const BorderValue* m_border; + Color m_borderColor; + EBorderPrecedence m_precedence; }; } // namespace WebCore diff --git a/WebCore/rendering/style/CursorData.h b/WebCore/rendering/style/CursorData.h index 7c6b31d..2341e71 100644 --- a/WebCore/rendering/style/CursorData.h +++ b/WebCore/rendering/style/CursorData.h @@ -31,15 +31,17 @@ namespace WebCore { -struct CursorData { - CursorData() - : cursorImage(0) +class CursorData { +public: + CursorData(CachedImage* image, const IntPoint& hotSpot) + : m_image(image) + , m_hotSpot(hotSpot) { } bool operator==(const CursorData& o) const { - return hotSpot == o.hotSpot && cursorImage == o.cursorImage; + return m_hotSpot == o.m_hotSpot && m_image == o.m_image; } bool operator!=(const CursorData& o) const @@ -47,8 +49,12 @@ struct CursorData { return !(*this == o); } - IntPoint hotSpot; // for CSS3 support - CachedResourceHandle<CachedImage> cursorImage; + const CachedImage* image() const { return m_image.get(); } + const IntPoint& hotSpot() const { return m_hotSpot; } + +private: + CachedResourceHandle<CachedImage> m_image; + IntPoint m_hotSpot; // for CSS3 support }; } // namespace WebCore diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h index cef6b19..eb21ec3 100644 --- a/WebCore/rendering/style/FillLayer.h +++ b/WebCore/rendering/style/FillLayer.h @@ -59,7 +59,7 @@ struct FillSize { LengthSize size; }; -struct FillLayer : FastAllocBase { +class FillLayer : public FastAllocBase { public: FillLayer(EFillLayerType); ~FillLayer(); @@ -74,6 +74,7 @@ public: EFillRepeat repeatY() const { return static_cast<EFillRepeat>(m_repeatY); } CompositeOperator composite() const { return static_cast<CompositeOperator>(m_composite); } LengthSize sizeLength() const { return m_sizeLength; } + EFillSizeType sizeType() const { return static_cast<EFillSizeType>(m_sizeType); } FillSize size() const { return FillSize(static_cast<EFillSizeType>(m_sizeType), m_sizeLength); } const FillLayer* next() const { return m_next; } @@ -161,9 +162,10 @@ public: static StyleImage* initialFillImage(EFillLayerType) { return 0; } private: + friend class RenderStyle; + FillLayer() { } -public: RefPtr<StyleImage> m_image; Length m_xPosition; diff --git a/WebCore/rendering/style/NinePieceImage.h b/WebCore/rendering/style/NinePieceImage.h index bf47ce6..c400551 100644 --- a/WebCore/rendering/style/NinePieceImage.h +++ b/WebCore/rendering/style/NinePieceImage.h @@ -55,10 +55,18 @@ public: bool hasImage() const { return m_image != 0; } StyleImage* image() const { return m_image.get(); } + void setImage(StyleImage* image) { m_image = image; } + const LengthBox& slices() const { return m_slices; } + void setSlices(const LengthBox& l) { m_slices = l; } + ENinePieceImageRule horizontalRule() const { return static_cast<ENinePieceImageRule>(m_horizontalRule); } - ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(m_verticalRule); } + void setHorizontalRule(ENinePieceImageRule rule) { m_horizontalRule = rule; } + ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(m_verticalRule); } + void setVerticalRule(ENinePieceImageRule rule) { m_verticalRule = rule; } + +private: RefPtr<StyleImage> m_image; LengthBox m_slices; unsigned m_horizontalRule : 2; // ENinePieceImageRule diff --git a/WebCore/rendering/style/OutlineValue.h b/WebCore/rendering/style/OutlineValue.h index 2628b7f..19c17a7 100644 --- a/WebCore/rendering/style/OutlineValue.h +++ b/WebCore/rendering/style/OutlineValue.h @@ -30,16 +30,17 @@ namespace WebCore { class OutlineValue : public BorderValue { +friend class RenderStyle; public: OutlineValue() - : _offset(0) - , _auto(false) + : m_offset(0) + , m_isAuto(false) { } bool operator==(const OutlineValue& o) const { - return width == o.width && m_style == o.m_style && color == o.color && _offset == o._offset && _auto == o._auto; + return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_offset == o.m_offset && m_isAuto == o.m_isAuto; } bool operator!=(const OutlineValue& o) const @@ -47,8 +48,12 @@ public: return !(*this == o); } - int _offset; - bool _auto; + int offset() const { return m_offset; } + bool isAuto() const { return m_isAuto; } + +private: + int m_offset; + bool m_isAuto; }; } // namespace WebCore diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 712344f..f1cf0bc 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -22,6 +22,7 @@ #include "config.h" #include "RenderStyle.h" +#include "CSSPropertyNames.h" #include "CSSStyleSelector.h" #include "CachedImage.h" #include "CounterContent.h" @@ -58,8 +59,7 @@ PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other) } RenderStyle::RenderStyle() - : m_pseudoState(PseudoUnknown) - , m_affectedByAttributeSelectors(false) + : m_affectedByAttributeSelectors(false) , m_unique(false) , m_affectedByEmpty(false) , m_emptyState(false) @@ -71,9 +71,9 @@ RenderStyle::RenderStyle() , m_firstChildState(false) , m_lastChildState(false) , m_childIndex(0) - , box(defaultStyle()->box) + , m_box(defaultStyle()->m_box) , visual(defaultStyle()->visual) - , background(defaultStyle()->background) + , m_background(defaultStyle()->m_background) , surround(defaultStyle()->surround) , rareNonInheritedData(defaultStyle()->rareNonInheritedData) , rareInheritedData(defaultStyle()->rareInheritedData) @@ -86,8 +86,7 @@ RenderStyle::RenderStyle() } RenderStyle::RenderStyle(bool) - : m_pseudoState(PseudoUnknown) - , m_affectedByAttributeSelectors(false) + : m_affectedByAttributeSelectors(false) , m_unique(false) , m_affectedByEmpty(false) , m_emptyState(false) @@ -102,9 +101,9 @@ RenderStyle::RenderStyle(bool) { setBitDefaults(); - box.init(); + m_box.init(); visual.init(); - background.init(); + m_background.init(); surround.init(); rareNonInheritedData.init(); rareNonInheritedData.access()->flexibleBox.init(); @@ -121,7 +120,6 @@ RenderStyle::RenderStyle(bool) RenderStyle::RenderStyle(const RenderStyle& o) : RefCounted<RenderStyle>() - , m_pseudoState(o.m_pseudoState) , m_affectedByAttributeSelectors(false) , m_unique(false) , m_affectedByEmpty(false) @@ -134,9 +132,9 @@ RenderStyle::RenderStyle(const RenderStyle& o) , m_firstChildState(false) , m_lastChildState(false) , m_childIndex(0) - , box(o.box) + , m_box(o.m_box) , visual(o.visual) - , background(o.background) + , m_background(o.m_background) , surround(o.surround) , rareNonInheritedData(o.rareNonInheritedData) , rareInheritedData(o.rareInheritedData) @@ -169,9 +167,9 @@ bool RenderStyle::operator==(const RenderStyle& o) const // compare everything except the pseudoStyle pointer return inherited_flags == o.inherited_flags && noninherited_flags == o.noninherited_flags && - box == o.box && + m_box == o.m_box && visual == o.visual && - background == o.background && + m_background == o.m_background && surround == o.surround && rareNonInheritedData == o.rareNonInheritedData && rareInheritedData == o.rareInheritedData && @@ -213,28 +211,39 @@ void RenderStyle::setHasPseudoStyle(PseudoId pseudo) RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const { - if (!m_cachedPseudoStyle || styleType() != NOPSEUDO) + ASSERT(styleType() != VISITED_LINK); + + if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size()) + return 0; + + if (styleType() != NOPSEUDO) { + if (pid == VISITED_LINK) + return m_cachedPseudoStyles->at(0)->styleType() == VISITED_LINK ? m_cachedPseudoStyles->at(0).get() : 0; return 0; - RenderStyle* ps = m_cachedPseudoStyle.get(); - while (ps && ps->styleType() != pid) - ps = ps->m_cachedPseudoStyle.get(); - return ps; + } + + for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) { + RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get(); + if (pseudoStyle->styleType() == pid) + return pseudoStyle; + } + + return 0; } RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo) { if (!pseudo) return 0; - pseudo->m_cachedPseudoStyle = m_cachedPseudoStyle; - m_cachedPseudoStyle = pseudo; - return m_cachedPseudoStyle.get(); -} + + RenderStyle* result = pseudo.get(); -void RenderStyle::getPseudoStyleCache(PseudoStyleCache& cache) const -{ - ASSERT(cache.isEmpty()); - for (RenderStyle* pseudoStyle = m_cachedPseudoStyle.get(); pseudoStyle; pseudoStyle = pseudoStyle->m_cachedPseudoStyle.get()) - cache.append(pseudoStyle); + if (!m_cachedPseudoStyles) + m_cachedPseudoStyles.set(new PseudoStyleCache); + + m_cachedPseudoStyles->append(pseudo); + + return result; } bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const @@ -297,18 +306,18 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon return StyleDifferenceLayout; #endif - if (box->width != other->box->width || - box->min_width != other->box->min_width || - box->max_width != other->box->max_width || - box->height != other->box->height || - box->min_height != other->box->min_height || - box->max_height != other->box->max_height) + if (m_box->width() != other->m_box->width() || + m_box->minWidth() != other->m_box->minWidth() || + m_box->maxWidth() != other->m_box->maxWidth() || + m_box->height() != other->m_box->height() || + m_box->minHeight() != other->m_box->minHeight() || + m_box->maxHeight() != other->m_box->maxHeight()) return StyleDifferenceLayout; - if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align) + if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align) return StyleDifferenceLayout; - if (box->boxSizing != other->box->boxSizing) + if (m_box->boxSizing() != other->m_box->boxSizing()) return StyleDifferenceLayout; if (surround->margin != other->surround->margin) @@ -480,7 +489,7 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon // return RepaintLayer; //else return StyleDifferenceLayout; - } else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto || + } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip) return StyleDifferenceRepaintLayer; } @@ -502,8 +511,9 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon inherited_flags._visibility != other->inherited_flags._visibility || inherited_flags._text_decorations != other->inherited_flags._text_decorations || inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white || + inherited_flags._insideLink != other->inherited_flags._insideLink || surround->border != other->surround->border || - *background.get() != *other->background.get() || + *m_background.get() != *other->m_background.get() || visual->textDecoration != other->visual->textDecoration || rareInheritedData->userModify != other->rareInheritedData->userModify || rareInheritedData->userSelect != other->rareInheritedData->userSelect || @@ -543,12 +553,9 @@ void RenderStyle::setClip(Length top, Length right, Length bottom, Length left) void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot) { - CursorData data; - data.cursorImage = image; - data.hotSpot = hotSpot; if (!inherited.access()->cursorData) inherited.access()->cursorData = CursorList::create(); - inherited.access()->cursorData->append(data); + inherited.access()->cursorData->append(CursorData(image, hotSpot)); } void RenderStyle::setCursorList(PassRefPtr<CursorList> other) @@ -707,7 +714,7 @@ void RenderStyle::addBindingURI(StringImpl* uri) void RenderStyle::setTextShadow(ShadowData* val, bool add) { - ASSERT(!val || (!val->spread && val->style == Normal)); + ASSERT(!val || (!val->spread() && val->style() == Normal)); StyleRareInheritedData* rareData = rareInheritedData.access(); if (!add) { @@ -716,7 +723,7 @@ void RenderStyle::setTextShadow(ShadowData* val, bool add) return; } - val->next = rareData->textShadow; + val->setNext(rareData->textShadow); rareData->textShadow = val; } @@ -728,17 +735,17 @@ void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add) return; } - shadowData->next = rareData->m_boxShadow.release(); + shadowData->setNext(rareData->m_boxShadow.release()); rareData->m_boxShadow.set(shadowData); } void RenderStyle::getBorderRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const { - topLeft = surround->border.topLeft; - topRight = surround->border.topRight; + topLeft = surround->border.topLeft(); + topRight = surround->border.topRight(); - bottomLeft = surround->border.bottomLeft; - bottomRight = surround->border.bottomRight; + bottomLeft = surround->border.bottomLeft(); + bottomRight = surround->border.bottomRight(); // Constrain corner radii using CSS3 rules: // http://www.w3.org/TR/css3-background/#the-border-radius @@ -925,15 +932,15 @@ void RenderStyle::getBoxShadowExtent(int &top, int &right, int &bottom, int &lef bottom = 0; left = 0; - for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) { - if (boxShadow->style == Inset) + for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) { + if (boxShadow->style() == Inset) continue; - int blurAndSpread = boxShadow->blur + boxShadow->spread; + int blurAndSpread = boxShadow->blur() + boxShadow->spread(); - top = min(top, boxShadow->y - blurAndSpread); - right = max(right, boxShadow->x + blurAndSpread); - bottom = max(bottom, boxShadow->y + blurAndSpread); - left = min(left, boxShadow->x - blurAndSpread); + top = min(top, boxShadow->y() - blurAndSpread); + right = max(right, boxShadow->x() + blurAndSpread); + bottom = max(bottom, boxShadow->y() + blurAndSpread); + left = min(left, boxShadow->x() - blurAndSpread); } } @@ -942,13 +949,13 @@ void RenderStyle::getBoxShadowHorizontalExtent(int &left, int &right) const left = 0; right = 0; - for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) { - if (boxShadow->style == Inset) + for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) { + if (boxShadow->style() == Inset) continue; - int blurAndSpread = boxShadow->blur + boxShadow->spread; + int blurAndSpread = boxShadow->blur() + boxShadow->spread(); - left = min(left, boxShadow->x - blurAndSpread); - right = max(right, boxShadow->x + blurAndSpread); + left = min(left, boxShadow->x() - blurAndSpread); + right = max(right, boxShadow->x() + blurAndSpread); } } @@ -957,14 +964,108 @@ void RenderStyle::getBoxShadowVerticalExtent(int &top, int &bottom) const top = 0; bottom = 0; - for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) { - if (boxShadow->style == Inset) + for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) { + if (boxShadow->style() == Inset) continue; - int blurAndSpread = boxShadow->blur + boxShadow->spread; + int blurAndSpread = boxShadow->blur() + boxShadow->spread(); - top = min(top, boxShadow->y - blurAndSpread); - bottom = max(bottom, boxShadow->y + blurAndSpread); + top = min(top, boxShadow->y() - blurAndSpread); + bottom = max(bottom, boxShadow->y() + blurAndSpread); } } +static EBorderStyle borderStyleForColorProperty(const RenderStyle* style, int colorProperty) +{ + EBorderStyle borderStyle; + switch (colorProperty) { + case CSSPropertyBorderLeftColor: + borderStyle = style->borderLeftStyle(); + break; + case CSSPropertyBorderRightColor: + borderStyle = style->borderRightStyle(); + break; + case CSSPropertyBorderTopColor: + borderStyle = style->borderTopStyle(); + break; + case CSSPropertyBorderBottomColor: + borderStyle = style->borderBottomStyle(); + break; + default: + borderStyle = BNONE; + break; + } + return borderStyle; +} + +static Color colorIncludingFallback(const RenderStyle* style, int colorProperty, EBorderStyle borderStyle) +{ + Color result; + switch (colorProperty) { + case CSSPropertyBackgroundColor: + return style->backgroundColor(); // Background color doesn't fall back. + case CSSPropertyBorderLeftColor: + result = style->borderLeftColor(); + borderStyle = style->borderLeftStyle(); + break; + case CSSPropertyBorderRightColor: + result = style->borderRightColor(); + borderStyle = style->borderRightStyle(); + break; + case CSSPropertyBorderTopColor: + result = style->borderTopColor(); + borderStyle = style->borderTopStyle(); + break; + case CSSPropertyBorderBottomColor: + result = style->borderBottomColor(); + borderStyle = style->borderBottomStyle(); + break; + case CSSPropertyColor: + result = style->color(); + break; + case CSSPropertyOutlineColor: + result = style->outlineColor(); + break; + case CSSPropertyWebkitColumnRuleColor: + result = style->columnRuleColor(); + break; + case CSSPropertyWebkitTextFillColor: + result = style->textFillColor(); + break; + case CSSPropertyWebkitTextStrokeColor: + result = style->textStrokeColor(); + break; + default: + // FIXME: Add SVG fill and stroke. + ASSERT_NOT_REACHED(); + break; + } + + if (!result.isValid()) { + if ((colorProperty == CSSPropertyBorderLeftColor || colorProperty == CSSPropertyBorderRightColor + || colorProperty == CSSPropertyBorderTopColor || colorProperty == CSSPropertyBorderBottomColor) + && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE)) + result.setRGB(238, 238, 238); + else + result = style->color(); + } + + return result; +} + +Color RenderStyle::visitedDependentColor(int colorProperty) const +{ + EBorderStyle borderStyle = borderStyleForColorProperty(this, colorProperty); + Color unvisitedColor = colorIncludingFallback(this, colorProperty, borderStyle); + if (insideLink() != InsideVisitedLink) + return unvisitedColor; + + RenderStyle* visitedStyle = getCachedPseudoStyle(VISITED_LINK); + if (!visitedStyle) + return unvisitedColor; + Color visitedColor = colorIncludingFallback(visitedStyle, colorProperty, borderStyle); + + // Take the alpha from the unvisited color, but get the RGB values from the visited color. + return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha()); +} + } // namespace WebCore diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index c7db254..fe42339 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -110,13 +110,14 @@ class Pair; class StringImpl; class StyleImage; +typedef Vector<RefPtr<RenderStyle>, 4> PseudoStyleCache; + class RenderStyle: public RefCounted<RenderStyle> { friend class CSSStyleSelector; protected: // The following bitfield is 32-bits long, which optimizes padding with the // int refCount in the base class. Beware when adding more bits. - unsigned m_pseudoState : 3; // PseudoState bool m_affectedByAttributeSelectors : 1; bool m_unique : 1; @@ -133,12 +134,12 @@ protected: bool m_childrenAffectedByBackwardPositionalRules : 1; bool m_firstChildState : 1; bool m_lastChildState : 1; - unsigned m_childIndex : 18; // Plenty of bits to cache an index. + unsigned m_childIndex : 21; // Plenty of bits to cache an index. // non-inherited attributes - DataRef<StyleBoxData> box; + DataRef<StyleBoxData> m_box; DataRef<StyleVisualData> visual; - DataRef<StyleBackgroundData> background; + DataRef<StyleBackgroundData> m_background; DataRef<StyleSurroundData> surround; DataRef<StyleRareNonInheritedData> rareNonInheritedData; @@ -147,7 +148,7 @@ protected: DataRef<StyleInheritedData> inherited; // list of associated pseudo styles - RefPtr<RenderStyle> m_cachedPseudoStyle; + OwnPtr<PseudoStyleCache> m_cachedPseudoStyles; #if ENABLE(SVG) DataRef<SVGRenderStyle> m_svgStyle; @@ -176,7 +177,8 @@ protected: (_visuallyOrdered == other._visuallyOrdered) && (_htmlHacks == other._htmlHacks) && (_force_backgrounds_to_white == other._force_backgrounds_to_white) && - (_pointerEvents == other._pointerEvents); + (_pointerEvents == other._pointerEvents) && + (_insideLink == other._insideLink); } bool operator!=(const InheritedFlags& other) const { return !(*this == other); } @@ -201,7 +203,8 @@ protected: bool _htmlHacks : 1; bool _force_backgrounds_to_white : 1; unsigned _pointerEvents : 4; // EPointerEvents - // 41 bits + unsigned _insideLink : 2; // EInsideLink + // 43 bits } inherited_flags; // don't inherit @@ -225,7 +228,8 @@ protected: && _affectedByActive == other._affectedByActive && _affectedByDrag == other._affectedByDrag && _pseudoBits == other._pseudoBits - && _unicodeBidi == other._unicodeBidi; + && _unicodeBidi == other._unicodeBidi + && _isLink == other._isLink; } bool operator!=(const NonInheritedFlags& other) const { return !(*this == other); } @@ -244,12 +248,13 @@ protected: unsigned _page_break_after : 2; // EPageBreak unsigned _page_break_inside : 2; // EPageBreak - unsigned _styleType : 5; // PseudoId + unsigned _styleType : 6; // PseudoId bool _affectedByHover : 1; bool _affectedByActive : 1; bool _affectedByDrag : 1; unsigned _pseudoBits : 7; unsigned _unicodeBidi : 2; // EUnicodeBidi + bool _isLink : 1; // 50 bits } noninherited_flags; @@ -275,6 +280,7 @@ protected: inherited_flags._box_direction = initialBoxDirection(); inherited_flags._force_backgrounds_to_white = false; inherited_flags._pointerEvents = initialPointerEvents(); + inherited_flags._insideLink = NotInsideLink; noninherited_flags._effectiveDisplay = noninherited_flags._originalDisplay = initialDisplay(); noninherited_flags._overflowX = initialOverflowX(); @@ -293,6 +299,7 @@ protected: noninherited_flags._affectedByDrag = false; noninherited_flags._pseudoBits = 0; noninherited_flags._unicodeBidi = initialUnicodeBidi(); + noninherited_flags._isLink = false; } protected: @@ -316,8 +323,7 @@ public: RenderStyle* getCachedPseudoStyle(PseudoId) const; RenderStyle* addCachedPseudoStyle(PassRefPtr<RenderStyle>); - typedef Vector<RenderStyle*, 10> PseudoStyleCache; - void getPseudoStyleCache(PseudoStyleCache&) const; + const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); } bool affectedByHoverRules() const { return noninherited_flags._affectedByHover; } bool affectedByActiveRules() const { return noninherited_flags._affectedByActive; } @@ -339,10 +345,10 @@ public: { if (backgroundColor().isValid() && backgroundColor().alpha() > 0) return true; - return background->m_background.hasImage(); + return m_background->background().hasImage(); } - bool hasBackgroundImage() const { return background->m_background.hasImage(); } - bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); } + bool hasBackgroundImage() const { return m_background->background().hasImage(); } + bool hasFixedBackgroundImage() const { return m_background->background().hasFixedImage(); } bool hasAppearance() const { return appearance() != NoControlPart; } bool visuallyOrdered() const { return inherited_flags._visuallyOrdered; } @@ -372,62 +378,62 @@ public: EPosition position() const { return static_cast<EPosition>(noninherited_flags._position); } EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); } - Length width() const { return box->width; } - Length height() const { return box->height; } - Length minWidth() const { return box->min_width; } - Length maxWidth() const { return box->max_width; } - Length minHeight() const { return box->min_height; } - Length maxHeight() const { return box->max_height; } + Length width() const { return m_box->width(); } + Length height() const { return m_box->height(); } + Length minWidth() const { return m_box->minWidth(); } + Length maxWidth() const { return m_box->maxWidth(); } + Length minHeight() const { return m_box->minHeight(); } + Length maxHeight() const { return m_box->maxHeight(); } const BorderData& border() const { return surround->border; } - const BorderValue& borderLeft() const { return surround->border.left; } - const BorderValue& borderRight() const { return surround->border.right; } - const BorderValue& borderTop() const { return surround->border.top; } - const BorderValue& borderBottom() const { return surround->border.bottom; } + const BorderValue& borderLeft() const { return surround->border.left(); } + const BorderValue& borderRight() const { return surround->border.right(); } + const BorderValue& borderTop() const { return surround->border.top(); } + const BorderValue& borderBottom() const { return surround->border.bottom(); } - const NinePieceImage& borderImage() const { return surround->border.image; } + const NinePieceImage& borderImage() const { return surround->border.image(); } - const IntSize& borderTopLeftRadius() const { return surround->border.topLeft; } - const IntSize& borderTopRightRadius() const { return surround->border.topRight; } - const IntSize& borderBottomLeftRadius() const { return surround->border.bottomLeft; } - const IntSize& borderBottomRightRadius() const { return surround->border.bottomRight; } + const IntSize& borderTopLeftRadius() const { return surround->border.topLeft(); } + const IntSize& borderTopRightRadius() const { return surround->border.topRight(); } + const IntSize& borderBottomLeftRadius() const { return surround->border.bottomLeft(); } + const IntSize& borderBottomRightRadius() const { return surround->border.bottomRight(); } bool hasBorderRadius() const { return surround->border.hasBorderRadius(); } unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); } - EBorderStyle borderLeftStyle() const { return surround->border.left.style(); } - const Color& borderLeftColor() const { return surround->border.left.color; } - bool borderLeftIsTransparent() const { return surround->border.left.isTransparent(); } + EBorderStyle borderLeftStyle() const { return surround->border.left().style(); } + const Color& borderLeftColor() const { return surround->border.left().color(); } + bool borderLeftIsTransparent() const { return surround->border.left().isTransparent(); } unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); } - EBorderStyle borderRightStyle() const { return surround->border.right.style(); } - const Color& borderRightColor() const { return surround->border.right.color; } - bool borderRightIsTransparent() const { return surround->border.right.isTransparent(); } + EBorderStyle borderRightStyle() const { return surround->border.right().style(); } + const Color& borderRightColor() const { return surround->border.right().color(); } + bool borderRightIsTransparent() const { return surround->border.right().isTransparent(); } unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); } - EBorderStyle borderTopStyle() const { return surround->border.top.style(); } - const Color& borderTopColor() const { return surround->border.top.color; } - bool borderTopIsTransparent() const { return surround->border.top.isTransparent(); } + EBorderStyle borderTopStyle() const { return surround->border.top().style(); } + const Color& borderTopColor() const { return surround->border.top().color(); } + bool borderTopIsTransparent() const { return surround->border.top().isTransparent(); } unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); } - EBorderStyle borderBottomStyle() const { return surround->border.bottom.style(); } - const Color& borderBottomColor() const { return surround->border.bottom.color; } - bool borderBottomIsTransparent() const { return surround->border.bottom.isTransparent(); } + EBorderStyle borderBottomStyle() const { return surround->border.bottom().style(); } + const Color& borderBottomColor() const { return surround->border.bottom().color(); } + bool borderBottomIsTransparent() const { return surround->border.bottom().isTransparent(); } unsigned short outlineSize() const { return max(0, outlineWidth() + outlineOffset()); } unsigned short outlineWidth() const { - if (background->m_outline.style() == BNONE) + if (m_background->outline().style() == BNONE) return 0; - return background->m_outline.width; + return m_background->outline().width(); } bool hasOutline() const { return outlineWidth() > 0 && outlineStyle() > BHIDDEN; } - EBorderStyle outlineStyle() const { return background->m_outline.style(); } - bool outlineStyleIsAuto() const { return background->m_outline._auto; } - const Color& outlineColor() const { return background->m_outline.color; } + EBorderStyle outlineStyle() const { return m_background->outline().style(); } + bool outlineStyleIsAuto() const { return m_background->outline().isAuto(); } + const Color& outlineColor() const { return m_background->outline().color(); } EOverflow overflowX() const { return static_cast<EOverflow>(noninherited_flags._overflowX); } EOverflow overflowY() const { return static_cast<EOverflow>(noninherited_flags._overflowY); } EVisibility visibility() const { return static_cast<EVisibility>(inherited_flags._visibility); } EVerticalAlign verticalAlign() const { return static_cast<EVerticalAlign>(noninherited_flags._vertical_align); } - Length verticalAlignLength() const { return box->vertical_align; } + Length verticalAlignLength() const { return m_box->verticalAlign(); } Length clipLeft() const { return visual->clip.left(); } Length clipRight() const { return visual->clip.right(); } @@ -529,31 +535,32 @@ public: return wordBreak() == BreakWordBreak || wordWrap() == BreakWordWrap; } - const Color& backgroundColor() const { return background->m_color; } - StyleImage* backgroundImage() const { return background->m_background.m_image.get(); } - EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(background->m_background.m_repeatX); } - EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(background->m_background.m_repeatY); } - CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(background->m_background.m_composite); } - EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(background->m_background.m_attachment); } - EFillBox backgroundClip() const { return static_cast<EFillBox>(background->m_background.m_clip); } - EFillBox backgroundOrigin() const { return static_cast<EFillBox>(background->m_background.m_origin); } - Length backgroundXPosition() const { return background->m_background.m_xPosition; } - Length backgroundYPosition() const { return background->m_background.m_yPosition; } - EFillSizeType backgroundSizeType() const { return static_cast<EFillSizeType>(background->m_background.m_sizeType); } - LengthSize backgroundSizeLength() const { return background->m_background.m_sizeLength; } - FillLayer* accessBackgroundLayers() { return &(background.access()->m_background); } - const FillLayer* backgroundLayers() const { return &(background->m_background); } - - StyleImage* maskImage() const { return rareNonInheritedData->m_mask.m_image.get(); } - EFillRepeat maskRepeatX() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeatX); } - EFillRepeat maskRepeatY() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeatY); } - CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.m_composite); } - EFillAttachment maskAttachment() const { return static_cast<EFillAttachment>(rareNonInheritedData->m_mask.m_attachment); } - EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_clip); } - EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_origin); } - Length maskXPosition() const { return rareNonInheritedData->m_mask.m_xPosition; } - Length maskYPosition() const { return rareNonInheritedData->m_mask.m_yPosition; } - LengthSize maskSize() const { return rareNonInheritedData->m_mask.m_sizeLength; } + const Color& backgroundColor() const { return m_background->color(); } + StyleImage* backgroundImage() const { return m_background->background().image(); } + EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(m_background->background().repeatX()); } + EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(m_background->background().repeatY()); } + CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(m_background->background().composite()); } + EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(m_background->background().attachment()); } + EFillBox backgroundClip() const { return static_cast<EFillBox>(m_background->background().clip()); } + EFillBox backgroundOrigin() const { return static_cast<EFillBox>(m_background->background().origin()); } + Length backgroundXPosition() const { return m_background->background().xPosition(); } + Length backgroundYPosition() const { return m_background->background().yPosition(); } + EFillSizeType backgroundSizeType() const { return m_background->background().sizeType(); } + LengthSize backgroundSizeLength() const { return m_background->background().sizeLength(); } + FillLayer* accessBackgroundLayers() { return &(m_background.access()->m_background); } + const FillLayer* backgroundLayers() const { return &(m_background->background()); } + + StyleImage* maskImage() const { return rareNonInheritedData->m_mask.image(); } + EFillRepeat maskRepeatX() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.repeatX()); } + EFillRepeat maskRepeatY() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.repeatY()); } + CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.composite()); } + EFillAttachment maskAttachment() const { return static_cast<EFillAttachment>(rareNonInheritedData->m_mask.attachment()); } + EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.clip()); } + EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.origin()); } + Length maskXPosition() const { return rareNonInheritedData->m_mask.xPosition(); } + Length maskYPosition() const { return rareNonInheritedData->m_mask.yPosition(); } + EFillSizeType maskSizeType() const { return rareNonInheritedData->m_mask.sizeType(); } + LengthSize maskSizeLength() const { return rareNonInheritedData->m_mask.sizeLength(); } FillLayer* accessMaskLayers() { return &(rareNonInheritedData.access()->m_mask); } const FillLayer* maskLayers() const { return &(rareNonInheritedData->m_mask); } const NinePieceImage& maskBoxImage() const { return rareNonInheritedData->m_maskBoxImage; } @@ -587,6 +594,9 @@ public: CursorList* cursors() const { return inherited->cursorData.get(); } + EInsideLink insideLink() const { return static_cast<EInsideLink>(inherited_flags._insideLink); } + bool isLink() const { return noninherited_flags._isLink; } + short widows() const { return inherited->widows; } short orphans() const { return inherited->orphans; } EPageBreak pageBreakInside() const { return static_cast<EPageBreak>(noninherited_flags._page_break_inside); } @@ -600,12 +610,12 @@ public: int outlineOffset() const { - if (background->m_outline.style() == BNONE) + if (m_background->outline().style() == BNONE) return 0; - return background->m_outline._offset; + return m_background->outline().offset(); } - ShadowData* textShadow() const { return rareInheritedData->textShadow; } + const ShadowData* textShadow() const { return rareInheritedData->textShadow; } const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; } const Color& textFillColor() const { return rareInheritedData->textFillColor; } @@ -621,13 +631,13 @@ public: EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->flexibleBox->orient); } EBoxAlignment boxPack() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->pack); } - ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); } + const ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); } void getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const; void getBoxShadowHorizontalExtent(int &left, int &right) const; void getBoxShadowVerticalExtent(int &top, int &bottom) const; StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); } - EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(box->boxSizing); } + EBoxSizing boxSizing() const { return m_box->boxSizing(); } Length marqueeIncrement() const { return rareNonInheritedData->marquee->increment; } int marqueeSpeed() const { return rareNonInheritedData->marquee->speed; } int marqueeLoopCount() const { return rareNonInheritedData->marquee->loops; } @@ -653,7 +663,7 @@ public: bool hasAutoColumnCount() const { return rareNonInheritedData->m_multiCol->m_autoCount; } float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; } bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; } - const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color; } + const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); } EBorderStyle columnRuleStyle() const { return rareNonInheritedData->m_multiCol->m_rule.style(); } unsigned short columnRuleWidth() const { return rareNonInheritedData->m_multiCol->ruleWidth(); } bool columnRuleIsTransparent() const { return rareNonInheritedData->m_multiCol->m_rule.isTransparent(); } @@ -724,13 +734,13 @@ public: void setTop(Length v) { SET_VAR(surround, offset.m_top, v) } void setBottom(Length v) { SET_VAR(surround, offset.m_bottom, v) } - void setWidth(Length v) { SET_VAR(box, width, v) } - void setHeight(Length v) { SET_VAR(box, height, v) } + void setWidth(Length v) { SET_VAR(m_box, m_width, v) } + void setHeight(Length v) { SET_VAR(m_box, m_height, v) } - void setMinWidth(Length v) { SET_VAR(box, min_width, v) } - void setMaxWidth(Length v) { SET_VAR(box, max_width, v) } - void setMinHeight(Length v) { SET_VAR(box, min_height, v) } - void setMaxHeight(Length v) { SET_VAR(box, max_height, v) } + void setMinWidth(Length v) { SET_VAR(m_box, m_minWidth, v) } + void setMaxWidth(Length v) { SET_VAR(m_box, m_maxWidth, v) } + void setMinHeight(Length v) { SET_VAR(m_box, m_minHeight, v) } + void setMaxHeight(Length v) { SET_VAR(m_box, m_maxHeight, v) } #if ENABLE(DASHBOARD_SUPPORT) Vector<StyleDashboardRegion> dashboardRegions() const { return rareNonInheritedData->m_dashboardRegions; } @@ -752,32 +762,32 @@ public: #endif void resetBorder() { resetBorderImage(); resetBorderTop(); resetBorderRight(); resetBorderBottom(); resetBorderLeft(); resetBorderRadius(); } - void resetBorderTop() { SET_VAR(surround, border.top, BorderValue()) } - void resetBorderRight() { SET_VAR(surround, border.right, BorderValue()) } - void resetBorderBottom() { SET_VAR(surround, border.bottom, BorderValue()) } - void resetBorderLeft() { SET_VAR(surround, border.left, BorderValue()) } - void resetBorderImage() { SET_VAR(surround, border.image, NinePieceImage()) } + void resetBorderTop() { SET_VAR(surround, border.m_top, BorderValue()) } + void resetBorderRight() { SET_VAR(surround, border.m_right, BorderValue()) } + void resetBorderBottom() { SET_VAR(surround, border.m_bottom, BorderValue()) } + void resetBorderLeft() { SET_VAR(surround, border.m_left, BorderValue()) } + void resetBorderImage() { SET_VAR(surround, border.m_image, NinePieceImage()) } void resetBorderRadius() { resetBorderTopLeftRadius(); resetBorderTopRightRadius(); resetBorderBottomLeftRadius(); resetBorderBottomRightRadius(); } - void resetBorderTopLeftRadius() { SET_VAR(surround, border.topLeft, initialBorderRadius()) } - void resetBorderTopRightRadius() { SET_VAR(surround, border.topRight, initialBorderRadius()) } - void resetBorderBottomLeftRadius() { SET_VAR(surround, border.bottomLeft, initialBorderRadius()) } - void resetBorderBottomRightRadius() { SET_VAR(surround, border.bottomRight, initialBorderRadius()) } + void resetBorderTopLeftRadius() { SET_VAR(surround, border.m_topLeft, initialBorderRadius()) } + void resetBorderTopRightRadius() { SET_VAR(surround, border.m_topRight, initialBorderRadius()) } + void resetBorderBottomLeftRadius() { SET_VAR(surround, border.m_bottomLeft, initialBorderRadius()) } + void resetBorderBottomRightRadius() { SET_VAR(surround, border.m_bottomRight, initialBorderRadius()) } - void resetOutline() { SET_VAR(background, m_outline, OutlineValue()) } + void resetOutline() { SET_VAR(m_background, m_outline, OutlineValue()) } - void setBackgroundColor(const Color& v) { SET_VAR(background, m_color, v) } + void setBackgroundColor(const Color& v) { SET_VAR(m_background, m_color, v) } - void setBackgroundXPosition(Length l) { SET_VAR(background, m_background.m_xPosition, l) } - void setBackgroundYPosition(Length l) { SET_VAR(background, m_background.m_yPosition, l) } - void setBackgroundSize(EFillSizeType b) { SET_VAR(background, m_background.m_sizeType, b) } - void setBackgroundSizeLength(LengthSize l) { SET_VAR(background, m_background.m_sizeLength, l) } + void setBackgroundXPosition(Length l) { SET_VAR(m_background, m_background.m_xPosition, l) } + void setBackgroundYPosition(Length l) { SET_VAR(m_background, m_background.m_yPosition, l) } + void setBackgroundSize(EFillSizeType b) { SET_VAR(m_background, m_background.m_sizeType, b) } + void setBackgroundSizeLength(LengthSize l) { SET_VAR(m_background, m_background.m_sizeLength, l) } - void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.image, b) } + void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.m_image, b) } - void setBorderTopLeftRadius(const IntSize& s) { SET_VAR(surround, border.topLeft, s) } - void setBorderTopRightRadius(const IntSize& s) { SET_VAR(surround, border.topRight, s) } - void setBorderBottomLeftRadius(const IntSize& s) { SET_VAR(surround, border.bottomLeft, s) } - void setBorderBottomRightRadius(const IntSize& s) { SET_VAR(surround, border.bottomRight, s) } + void setBorderTopLeftRadius(const IntSize& s) { SET_VAR(surround, border.m_topLeft, s) } + void setBorderTopRightRadius(const IntSize& s) { SET_VAR(surround, border.m_topRight, s) } + void setBorderBottomLeftRadius(const IntSize& s) { SET_VAR(surround, border.m_bottomLeft, s) } + void setBorderBottomRightRadius(const IntSize& s) { SET_VAR(surround, border.m_bottomRight, s) } void setBorderRadius(const IntSize& s) { @@ -789,33 +799,33 @@ public: void getBorderRadiiForRect(const IntRect&, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const; - void setBorderLeftWidth(unsigned short v) { SET_VAR(surround, border.left.width, v) } - void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.left.m_style, v) } - void setBorderLeftColor(const Color& v) { SET_VAR(surround, border.left.color, v) } - void setBorderRightWidth(unsigned short v) { SET_VAR(surround, border.right.width, v) } - void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround, border.right.m_style, v) } - void setBorderRightColor(const Color& v) { SET_VAR(surround, border.right.color, v) } - void setBorderTopWidth(unsigned short v) { SET_VAR(surround, border.top.width, v) } - void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround, border.top.m_style, v) } - void setBorderTopColor(const Color& v) { SET_VAR(surround, border.top.color, v) } - void setBorderBottomWidth(unsigned short v) { SET_VAR(surround, border.bottom.width, v) } - void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround, border.bottom.m_style, v) } - void setBorderBottomColor(const Color& v) { SET_VAR(surround, border.bottom.color, v) } - void setOutlineWidth(unsigned short v) { SET_VAR(background, m_outline.width, v) } + void setBorderLeftWidth(unsigned short v) { SET_VAR(surround, border.m_left.m_width, v) } + void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.m_left.m_style, v) } + void setBorderLeftColor(const Color& v) { SET_VAR(surround, border.m_left.m_color, v) } + void setBorderRightWidth(unsigned short v) { SET_VAR(surround, border.m_right.m_width, v) } + void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround, border.m_right.m_style, v) } + void setBorderRightColor(const Color& v) { SET_VAR(surround, border.m_right.m_color, v) } + void setBorderTopWidth(unsigned short v) { SET_VAR(surround, border.m_top.m_width, v) } + void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround, border.m_top.m_style, v) } + void setBorderTopColor(const Color& v) { SET_VAR(surround, border.m_top.m_color, v) } + void setBorderBottomWidth(unsigned short v) { SET_VAR(surround, border.m_bottom.m_width, v) } + void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround, border.m_bottom.m_style, v) } + void setBorderBottomColor(const Color& v) { SET_VAR(surround, border.m_bottom.m_color, v) } + void setOutlineWidth(unsigned short v) { SET_VAR(m_background, m_outline.m_width, v) } void setOutlineStyle(EBorderStyle v, bool isAuto = false) { - SET_VAR(background, m_outline.m_style, v) - SET_VAR(background, m_outline._auto, isAuto) + SET_VAR(m_background, m_outline.m_style, v) + SET_VAR(m_background, m_outline.m_isAuto, isAuto) } - void setOutlineColor(const Color& v) { SET_VAR(background, m_outline.color, v) } + void setOutlineColor(const Color& v) { SET_VAR(m_background, m_outline.m_color, v) } void setOverflowX(EOverflow v) { noninherited_flags._overflowX = v; } void setOverflowY(EOverflow v) { noninherited_flags._overflowY = v; } void setVisibility(EVisibility v) { inherited_flags._visibility = v; } void setVerticalAlign(EVerticalAlign v) { noninherited_flags._vertical_align = v; } - void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l) } + void setVerticalAlignLength(Length l) { SET_VAR(m_box, m_verticalAlign, l) } void setHasClip(bool b = true) { SET_VAR(visual, hasClip, b) } void setClipLeft(Length v) { SET_VAR(visual, clip.m_left, v) } @@ -858,8 +868,8 @@ public: void setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); } void setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); } - void clearBackgroundLayers() { background.access()->m_background = FillLayer(BackgroundFillLayer); } - void inheritBackgroundLayers(const FillLayer& parent) { background.access()->m_background = parent; } + void clearBackgroundLayers() { m_background.access()->m_background = FillLayer(BackgroundFillLayer); } + void inheritBackgroundLayers(const FillLayer& parent) { m_background.access()->m_background = parent; } void adjustBackgroundLayers() { @@ -916,16 +926,19 @@ public: void setCursorList(PassRefPtr<CursorList>); void clearCursorList(); + void setInsideLink(EInsideLink insideLink) { inherited_flags._insideLink = insideLink; } + void setIsLink(bool b) { noninherited_flags._isLink = b; } + bool forceBackgroundsToWhite() const { return inherited_flags._force_backgrounds_to_white; } void setForceBackgroundsToWhite(bool b=true) { inherited_flags._force_backgrounds_to_white = b; } bool htmlHacks() const { return inherited_flags._htmlHacks; } void setHtmlHacks(bool b=true) { inherited_flags._htmlHacks = b; } - bool hasAutoZIndex() const { return box->z_auto; } - void setHasAutoZIndex() { SET_VAR(box, z_auto, true); SET_VAR(box, z_index, 0) } - int zIndex() const { return box->z_index; } - void setZIndex(int v) { SET_VAR(box, z_auto, false); SET_VAR(box, z_index, v) } + bool hasAutoZIndex() const { return m_box->hasAutoZIndex(); } + void setHasAutoZIndex() { SET_VAR(m_box, m_hasAutoZIndex, true); SET_VAR(m_box, m_zIndex, 0) } + int zIndex() const { return m_box->zIndex(); } + void setZIndex(int v) { SET_VAR(m_box, m_hasAutoZIndex, false); SET_VAR(m_box, m_zIndex, v) } void setWidows(short w) { SET_VAR(inherited, widows, w); } void setOrphans(short o) { SET_VAR(inherited, orphans, o); } @@ -940,7 +953,7 @@ public: void addBindingURI(StringImpl* uri); #endif - void setOutlineOffset(int v) { SET_VAR(background, m_outline._offset, v) } + void setOutlineOffset(int v) { SET_VAR(m_background, m_outline.m_offset, v) } void setTextShadow(ShadowData* val, bool add=false); void setTextStrokeColor(const Color& c) { SET_VAR(rareInheritedData, textStrokeColor, c) } void setTextStrokeWidth(float w) { SET_VAR(rareInheritedData, textStrokeWidth, w) } @@ -958,7 +971,7 @@ public: void setBoxPack(EBoxAlignment p) { SET_VAR(rareNonInheritedData.access()->flexibleBox, pack, p); } void setBoxShadow(ShadowData* val, bool add=false); void setBoxReflect(PassRefPtr<StyleReflection> reflect) { if (rareNonInheritedData->m_boxReflect != reflect) rareNonInheritedData.access()->m_boxReflect = reflect; } - void setBoxSizing(EBoxSizing s) { SET_VAR(box, boxSizing, s); } + void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); } void setMarqueeIncrement(const Length& f) { SET_VAR(rareNonInheritedData.access()->marquee, increment, f); } void setMarqueeSpeed(int f) { SET_VAR(rareNonInheritedData.access()->marquee, speed, f); } void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(rareNonInheritedData.access()->marquee, direction, d); } @@ -984,9 +997,9 @@ public: void setHasAutoColumnCount() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_autoCount, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_count, 0); } void setColumnGap(float f) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, false); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, f); } void setHasNormalColumnGap() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_normalGap, true); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_gap, 0); } - void setColumnRuleColor(const Color& c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.color, c); } + void setColumnRuleColor(const Color& c) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_color, c); } void setColumnRuleStyle(EBorderStyle b) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_style, b); } - void setColumnRuleWidth(unsigned short w) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.width, w); } + void setColumnRuleWidth(unsigned short w) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule.m_width, w); } void resetColumnRule() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule, BorderValue()) } void setColumnBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakBefore, p); } void setColumnBreakInside(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakInside, p); } @@ -1077,10 +1090,6 @@ public: originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE; } - // To obtain at any time the pseudo state for a given link. - PseudoState pseudoState() const { return static_cast<PseudoState>(m_pseudoState); } - void setPseudoState(PseudoState s) { m_pseudoState = s; } - // To tell if this style matched attribute selectors. This makes it impossible to share. bool affectedByAttributeSelectors() const { return m_affectedByAttributeSelectors; } void setAffectedByAttributeSelectors() { m_affectedByAttributeSelectors = true; } @@ -1110,6 +1119,8 @@ public: unsigned childIndex() const { return m_childIndex; } void setChildIndex(unsigned index) { m_childIndex = index; } + Color visitedDependentColor(int colorProperty) const; + // Initial values for all the properties static bool initialBorderCollapse() { return false; } static EBorderStyle initialBorderStyle() { return BNONE; } diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index 4abbc1c..b899d57 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -74,8 +74,9 @@ enum PseudoId { MEDIA_CONTROLS_SEEK_BACK_BUTTON, MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON, MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, - INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, + INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK, + AFTER_LAST_INTERNAL_PSEUDOID, FIRST_PUBLIC_PSEUDOID = FIRST_LINE, FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON, PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1) @@ -87,8 +88,6 @@ enum EBorderStyle { BNONE, BHIDDEN, INSET, GROOVE, RIDGE, OUTSET, DOTTED, DASHED enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL }; -enum PseudoState { PseudoUnknown, PseudoNone, PseudoAnyLink, PseudoLink, PseudoVisited}; - enum EPosition { StaticPosition, RelativePosition, AbsolutePosition, FixedPosition }; @@ -97,7 +96,6 @@ enum EFloat { FNONE = 0, FLEFT, FRIGHT }; - enum EMarginCollapse { MCOLLAPSE, MSEPARATE, MDISCARD }; // Box attributes. Not inherited. @@ -293,6 +291,8 @@ enum StyleContentType { enum EBorderFit { BorderFitBorder, BorderFitLines }; +enum EAnimationFillMode { AnimationFillModeNone, AnimationFillModeForwards, AnimationFillModeBackwards, AnimationFillModeBoth }; + enum EAnimPlayState { AnimPlayStatePlaying = 0x0, AnimPlayStatePaused = 0x1 @@ -386,6 +386,10 @@ enum EDisplay { NONE }; +enum EInsideLink { + NotInsideLink, InsideUnvisitedLink, InsideVisitedLink +}; + enum EPointerEvents { PE_NONE, PE_AUTO, PE_STROKE, PE_FILL, PE_PAINTED, PE_VISIBLE, PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index 7958088..042b8f7 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> + Copyright (C) Research In Motion Limited 2010. All rights reserved. Based on khtml code by: Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) @@ -25,6 +26,7 @@ */ #include "config.h" + #if ENABLE(SVG) #include "SVGRenderStyle.h" @@ -32,8 +34,6 @@ #include "CSSValueList.h" #include "IntRect.h" #include "NodeRenderStyle.h" -#include "RenderObject.h" -#include "RenderStyle.h" #include "SVGStyledElement.h" using namespace std; @@ -48,11 +48,10 @@ SVGRenderStyle::SVGRenderStyle() stroke = defaultStyle->stroke; text = defaultStyle->text; stops = defaultStyle->stops; - clip = defaultStyle->clip; - mask = defaultStyle->mask; misc = defaultStyle->misc; - markers = defaultStyle->markers; shadowSVG = defaultStyle->shadowSVG; + inheritedResources = defaultStyle->inheritedResources; + resources = defaultStyle->resources; setBitDefaults(); } @@ -65,11 +64,10 @@ SVGRenderStyle::SVGRenderStyle(CreateDefaultType) stroke.init(); text.init(); stops.init(); - clip.init(); - mask.init(); misc.init(); - markers.init(); shadowSVG.init(); + inheritedResources.init(); + resources.init(); } SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other) @@ -79,11 +77,10 @@ SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other) stroke = other.stroke; text = other.text; stops = other.stops; - clip = other.clip; - mask = other.mask; misc = other.misc; - markers = other.markers; shadowSVG = other.shadowSVG; + inheritedResources = other.inheritedResources; + resources = other.resources; svg_inherited_flags = other.svg_inherited_flags; svg_noninherited_flags = other.svg_noninherited_flags; @@ -93,22 +90,27 @@ SVGRenderStyle::~SVGRenderStyle() { } -bool SVGRenderStyle::operator==(const SVGRenderStyle& o) const +bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const { - return (fill == o.fill && stroke == o.stroke && text == o.text && - stops == o.stops && clip == o.clip && mask == o.mask && - misc == o.misc && markers == o.markers && shadowSVG == o.shadowSVG && - svg_inherited_flags == o.svg_inherited_flags && - svg_noninherited_flags == o.svg_noninherited_flags); + return fill == other.fill + && stroke == other.stroke + && text == other.text + && stops == other.stops + && misc == other.misc + && shadowSVG == other.shadowSVG + && inheritedResources == other.inheritedResources + && resources == other.resources + && svg_inherited_flags == other.svg_inherited_flags + && svg_noninherited_flags == other.svg_noninherited_flags; } bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const { - return (fill != other->fill - || stroke != other->stroke - || markers != other->markers - || text != other->text - || svg_inherited_flags != other->svg_inherited_flags); + return fill != other->fill + || stroke != other->stroke + || text != other->text + || inheritedResources != other->inheritedResources + || svg_inherited_flags != other->svg_inherited_flags; } void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent) @@ -118,8 +120,8 @@ void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent) fill = svgInheritParent->fill; stroke = svgInheritParent->stroke; - markers = svgInheritParent->markers; text = svgInheritParent->text; + inheritedResources = svgInheritParent->inheritedResources; svg_inherited_flags = svgInheritParent->svg_inherited_flags; } @@ -144,7 +146,6 @@ float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* v return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()), item->document()->documentElement()->renderStyle()); } - static void getSVGShadowExtent(ShadowData* shadow, int& top, int& right, int& bottom, int& left) { top = 0; @@ -152,12 +153,12 @@ static void getSVGShadowExtent(ShadowData* shadow, int& top, int& right, int& bo bottom = 0; left = 0; - int blurAndSpread = shadow->blur + shadow->spread; + int blurAndSpread = shadow->blur() + shadow->spread(); - top = min(top, shadow->y - blurAndSpread); - right = max(right, shadow->x + blurAndSpread); - bottom = max(bottom, shadow->y + blurAndSpread); - left = min(left, shadow->x - blurAndSpread); + top = min(top, shadow->y() - blurAndSpread); + right = max(right, shadow->x() + blurAndSpread); + bottom = max(bottom, shadow->y() + blurAndSpread); + left = min(left, shadow->x() - blurAndSpread); } void SVGRenderStyle::inflateForShadow(IntRect& repaintRect) const @@ -197,5 +198,3 @@ void SVGRenderStyle::inflateForShadow(FloatRect& repaintRect) const } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index c7f85db..c6d5022 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -2,6 +2,7 @@ Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> Copyright (C) 2005, 2006 Apple Computer, Inc. + Copyright (C) Research In Motion Limited 2010. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -26,11 +27,9 @@ #include "CSSValueList.h" #include "DataRef.h" #include "GraphicsTypes.h" +#include "Path.h" #include "SVGPaint.h" #include "SVGRenderStyleDefs.h" -#include "ShadowData.h" - -#include <wtf/Platform.h> namespace WebCore { @@ -91,13 +90,6 @@ public: SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, stops, opacity, StopOpacity, stopOpacity, 1.0f) SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, stops, color, StopColor, stopColor, Color(0, 0, 0)) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, clip, clipPath, ClipPath, clipPath, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, mask, maskElement, MaskElement, maskElement, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, startMarker, StartMarker, startMarker, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, midMarker, MidMarker, midMarker, String()) - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, markers, endMarker, EndMarker, endMarker, String()) - - SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, misc, filter, Filter, filter, String()) SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(float, misc, floodOpacity, FloodOpacity, floodOpacity, 1.0f) SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, floodColor, FloodColor, floodColor, Color(0, 0, 0)) SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(Color, misc, lightingColor, LightingColor, lightingColor, Color(255, 255, 255)) @@ -105,6 +97,16 @@ public: SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_OWNPTR(ShadowData, shadowSVG, shadow, Shadow, shadow, 0) + // Non-inherited resources + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, clipper, ClipperResource, clipperResource, String()) + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, filter, FilterResource, filterResource, String()) + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, resources, masker, MaskerResource, maskerResource, String()) + + // Inherited resources + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerStart, MarkerStartResource, markerStartResource, String()) + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerMid, MarkerMidResource, markerMidResource, String()) + SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerEnd, MarkerEndResource, markerEndResource, String()) + // convenience bool hasStroke() const { return (strokePaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); } bool hasFill() const { return (fillPaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); } @@ -171,15 +173,14 @@ protected: // inherited attributes DataRef<StyleFillData> fill; DataRef<StyleStrokeData> stroke; - DataRef<StyleMarkerData> markers; DataRef<StyleTextData> text; + DataRef<StyleInheritedResourceData> inheritedResources; // non-inherited attributes DataRef<StyleStopData> stops; - DataRef<StyleClipData> clip; - DataRef<StyleMaskData> mask; DataRef<StyleMiscData> misc; DataRef<StyleShadowSVGData> shadowSVG; + DataRef<StyleResourceData> resources; private: enum CreateDefaultType { CreateDefault }; @@ -215,5 +216,3 @@ private: #endif // ENABLE(SVG) #endif // SVGRenderStyle_h - -// vim:ts=4:noet diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.cpp b/WebCore/rendering/style/SVGRenderStyleDefs.cpp index 093f1f1..bf7624f 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.cpp +++ b/WebCore/rendering/style/SVGRenderStyleDefs.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2007 Rob Buis <buis@kde.org> + Copyright (C) Research In Motion Limited 2010. All rights reserved. Based on khtml code by: Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) @@ -25,28 +26,29 @@ */ #include "config.h" + #if ENABLE(SVG) #include "SVGRenderStyleDefs.h" #include "RenderStyle.h" #include "SVGRenderStyle.h" -using namespace WebCore; +namespace WebCore { StyleFillData::StyleFillData() + : opacity(SVGRenderStyle::initialFillOpacity()) + , paint(SVGRenderStyle::initialFillPaint()) { - paint = SVGRenderStyle::initialFillPaint(); - opacity = SVGRenderStyle::initialFillOpacity(); } StyleFillData::StyleFillData(const StyleFillData& other) : RefCounted<StyleFillData>() + , opacity(other.opacity) + , paint(other.paint) { - paint = other.paint; - opacity = other.opacity; } -bool StyleFillData::operator==(const StyleFillData &other) const +bool StyleFillData::operator==(const StyleFillData& other) const { if (opacity != other.opacity) return false; @@ -67,64 +69,64 @@ bool StyleFillData::operator==(const StyleFillData &other) const } StyleStrokeData::StyleStrokeData() + : opacity(SVGRenderStyle::initialStrokeOpacity()) + , miterLimit(SVGRenderStyle::initialStrokeMiterLimit()) + , width(SVGRenderStyle::initialStrokeWidth()) + , dashOffset(SVGRenderStyle::initialStrokeDashOffset()) + , paint(SVGRenderStyle::initialStrokePaint()) + , dashArray(SVGRenderStyle::initialStrokeDashArray()) { - width = SVGRenderStyle::initialStrokeWidth(); - paint = SVGRenderStyle::initialStrokePaint(); - opacity = SVGRenderStyle::initialStrokeOpacity(); - miterLimit = SVGRenderStyle::initialStrokeMiterLimit(); - dashOffset = SVGRenderStyle::initialStrokeDashOffset(); - dashArray = SVGRenderStyle::initialStrokeDashArray(); } StyleStrokeData::StyleStrokeData(const StyleStrokeData& other) : RefCounted<StyleStrokeData>() + , opacity(other.opacity) + , miterLimit(other.miterLimit) + , width(other.width) + , dashOffset(other.dashOffset) + , paint(other.paint) + , dashArray(other.dashArray) { - width = other.width; - paint = other.paint; - opacity = other.opacity; - miterLimit = other.miterLimit; - dashOffset = other.dashOffset; - dashArray = other.dashArray; } -bool StyleStrokeData::operator==(const StyleStrokeData &other) const +bool StyleStrokeData::operator==(const StyleStrokeData& other) const { - return (paint == other.paint) && - (width == other.width) && - (opacity == other.opacity) && - (miterLimit == other.miterLimit) && - (dashOffset == other.dashOffset) && - (dashArray == other.dashArray); + return paint == other.paint + && width == other.width + && opacity == other.opacity + && miterLimit == other.miterLimit + && dashOffset == other.dashOffset + && dashArray == other.dashArray; } StyleStopData::StyleStopData() + : opacity(SVGRenderStyle::initialStopOpacity()) + , color(SVGRenderStyle::initialStopColor()) { - color = SVGRenderStyle::initialStopColor(); - opacity = SVGRenderStyle::initialStopOpacity(); } StyleStopData::StyleStopData(const StyleStopData& other) : RefCounted<StyleStopData>() + , opacity(other.opacity) + , color(other.color) { - color = other.color; - opacity = other.opacity; } -bool StyleStopData::operator==(const StyleStopData &other) const +bool StyleStopData::operator==(const StyleStopData& other) const { - return (color == other.color) && - (opacity == other.opacity); + return color == other.color + && opacity == other.opacity; } StyleTextData::StyleTextData() + : kerning(SVGRenderStyle::initialKerning()) { - kerning = SVGRenderStyle::initialKerning(); } StyleTextData::StyleTextData(const StyleTextData& other) : RefCounted<StyleTextData>() + , kerning(other.kerning) { - kerning = other.kerning; } bool StyleTextData::operator==(const StyleTextData& other) const @@ -132,104 +134,94 @@ bool StyleTextData::operator==(const StyleTextData& other) const return kerning == other.kerning; } -StyleClipData::StyleClipData() -{ - clipPath = SVGRenderStyle::initialClipPath(); -} - -StyleClipData::StyleClipData(const StyleClipData& other) - : RefCounted<StyleClipData>() -{ - clipPath = other.clipPath; -} - -bool StyleClipData::operator==(const StyleClipData &other) const +StyleMiscData::StyleMiscData() + : floodColor(SVGRenderStyle::initialFloodColor()) + , floodOpacity(SVGRenderStyle::initialFloodOpacity()) + , lightingColor(SVGRenderStyle::initialLightingColor()) + , baselineShiftValue(SVGRenderStyle::initialBaselineShiftValue()) { - return (clipPath == other.clipPath); } -StyleMaskData::StyleMaskData() +StyleMiscData::StyleMiscData(const StyleMiscData& other) + : RefCounted<StyleMiscData>() + , floodColor(other.floodColor) + , floodOpacity(other.floodOpacity) + , lightingColor(other.lightingColor) + , baselineShiftValue(other.baselineShiftValue) { - maskElement = SVGRenderStyle::initialMaskElement(); } -StyleMaskData::StyleMaskData(const StyleMaskData& other) - : RefCounted<StyleMaskData>() +bool StyleMiscData::operator==(const StyleMiscData& other) const { - maskElement = other.maskElement; + return floodOpacity == other.floodOpacity + && floodColor == other.floodColor + && lightingColor == other.lightingColor + && baselineShiftValue == other.baselineShiftValue; } -bool StyleMaskData::operator==(const StyleMaskData &other) const +StyleShadowSVGData::StyleShadowSVGData() { - return (maskElement == other.maskElement); } -StyleMarkerData::StyleMarkerData() +StyleShadowSVGData::StyleShadowSVGData(const StyleShadowSVGData& other) + : RefCounted<StyleShadowSVGData>() + , shadow(other.shadow ? new ShadowData(*other.shadow) : 0) { - startMarker = SVGRenderStyle::initialStartMarker(); - midMarker = SVGRenderStyle::initialMidMarker(); - endMarker = SVGRenderStyle::initialEndMarker(); } -StyleMarkerData::StyleMarkerData(const StyleMarkerData& other) - : RefCounted<StyleMarkerData>() +bool StyleShadowSVGData::operator==(const StyleShadowSVGData& other) const { - startMarker = other.startMarker; - midMarker = other.midMarker; - endMarker = other.endMarker; + if ((!shadow && other.shadow) || (shadow && !other.shadow)) + return false; + if (shadow && other.shadow && (*shadow != *other.shadow)) + return false; + return true; } -bool StyleMarkerData::operator==(const StyleMarkerData &other) const +StyleResourceData::StyleResourceData() + : clipper(SVGRenderStyle::initialClipperResource()) + , filter(SVGRenderStyle::initialFilterResource()) + , masker(SVGRenderStyle::initialMaskerResource()) { - return (startMarker == other.startMarker && midMarker == other.midMarker && endMarker == other.endMarker); } -StyleMiscData::StyleMiscData() +StyleResourceData::StyleResourceData(const StyleResourceData& other) + : RefCounted<StyleResourceData>() + , clipper(other.clipper) + , filter(other.filter) + , masker(other.masker) { - floodColor = SVGRenderStyle::initialFloodColor(); - floodOpacity = SVGRenderStyle::initialFloodOpacity(); - lightingColor = SVGRenderStyle::initialLightingColor(); - baselineShiftValue = SVGRenderStyle::initialBaselineShiftValue(); } -StyleMiscData::StyleMiscData(const StyleMiscData& other) - : RefCounted<StyleMiscData>() +bool StyleResourceData::operator==(const StyleResourceData& other) const { - filter = other.filter; - floodColor = other.floodColor; - floodOpacity = other.floodOpacity; - lightingColor = other.lightingColor; - baselineShiftValue = other.baselineShiftValue; + return clipper == other.clipper + && filter == other.filter + && masker == other.masker; } -bool StyleMiscData::operator==(const StyleMiscData &other) const +StyleInheritedResourceData::StyleInheritedResourceData() + : markerStart(SVGRenderStyle::initialMarkerStartResource()) + , markerMid(SVGRenderStyle::initialMarkerMidResource()) + , markerEnd(SVGRenderStyle::initialMarkerEndResource()) { - return filter == other.filter - && floodOpacity == other.floodOpacity - && floodColor == other.floodColor - && lightingColor == other.lightingColor - && baselineShiftValue == other.baselineShiftValue; } -StyleShadowSVGData::StyleShadowSVGData() +StyleInheritedResourceData::StyleInheritedResourceData(const StyleInheritedResourceData& other) + : RefCounted<StyleInheritedResourceData>() + , markerStart(other.markerStart) + , markerMid(other.markerMid) + , markerEnd(other.markerEnd) { } -StyleShadowSVGData::StyleShadowSVGData(const StyleShadowSVGData& other) - : RefCounted<StyleShadowSVGData>() - , shadow(other.shadow ? new ShadowData(*other.shadow) : 0) +bool StyleInheritedResourceData::operator==(const StyleInheritedResourceData& other) const { + return markerStart == other.markerStart + && markerMid == other.markerMid + && markerEnd == other.markerEnd; } -bool StyleShadowSVGData::operator==(const StyleShadowSVGData& other) const -{ - if ((!shadow && other.shadow) || (shadow && !other.shadow)) - return false; - if (shadow && other.shadow && (*shadow != *other.shadow)) - return false; - return true; } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h index 8f01d9f..e0354e6 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.h +++ b/WebCore/rendering/style/SVGRenderStyleDefs.h @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> + Copyright (C) Research In Motion Limited 2010. All rights reserved. Based on khtml code by: Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) @@ -29,11 +30,9 @@ #if ENABLE(SVG) #include "Color.h" -#include "Path.h" #include "PlatformString.h" #include "ShadowData.h" #include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -133,8 +132,8 @@ namespace WebCore { static PassRefPtr<StyleFillData> create() { return adoptRef(new StyleFillData); } PassRefPtr<StyleFillData> copy() const { return adoptRef(new StyleFillData(*this)); } - bool operator==(const StyleFillData &other) const; - bool operator!=(const StyleFillData &other) const + bool operator==(const StyleFillData&) const; + bool operator!=(const StyleFillData& other) const { return !(*this == other); } @@ -177,8 +176,8 @@ namespace WebCore { static PassRefPtr<StyleStopData> create() { return adoptRef(new StyleStopData); } PassRefPtr<StyleStopData> copy() const { return adoptRef(new StyleStopData(*this)); } - bool operator==(const StyleStopData &other) const; - bool operator!=(const StyleStopData &other) const + bool operator==(const StyleStopData&) const; + bool operator!=(const StyleStopData& other) const { return !(*this == other); } @@ -206,109 +205,94 @@ namespace WebCore { private: StyleTextData(); - StyleTextData(const StyleTextData& other); + StyleTextData(const StyleTextData&); }; - class StyleClipData : public RefCounted<StyleClipData> { + // Note: the rule for this class is, *no inheritance* of these props + class StyleMiscData : public RefCounted<StyleMiscData> { public: - static PassRefPtr<StyleClipData> create() { return adoptRef(new StyleClipData); } - PassRefPtr<StyleClipData> copy() const { return adoptRef(new StyleClipData(*this)); } + static PassRefPtr<StyleMiscData> create() { return adoptRef(new StyleMiscData); } + PassRefPtr<StyleMiscData> copy() const { return adoptRef(new StyleMiscData(*this)); } - bool operator==(const StyleClipData &other) const; - bool operator!=(const StyleClipData &other) const + bool operator==(const StyleMiscData&) const; + bool operator!=(const StyleMiscData& other) const { return !(*this == other); } - String clipPath; - - private: - StyleClipData(); - StyleClipData(const StyleClipData&); - }; - - class StyleMaskData : public RefCounted<StyleMaskData> { - public: - static PassRefPtr<StyleMaskData> create() { return adoptRef(new StyleMaskData); } - PassRefPtr<StyleMaskData> copy() const { return adoptRef(new StyleMaskData(*this)); } - - bool operator==(const StyleMaskData &other) const; - bool operator!=(const StyleMaskData &other) const { return !(*this == other); } + Color floodColor; + float floodOpacity; + Color lightingColor; - String maskElement; + // non-inherited text stuff lives here not in StyleTextData. + RefPtr<CSSValue> baselineShiftValue; - private: - StyleMaskData(); - StyleMaskData(const StyleMaskData&); + private: + StyleMiscData(); + StyleMiscData(const StyleMiscData&); }; - class StyleMarkerData : public RefCounted<StyleMarkerData> { + class StyleShadowSVGData : public RefCounted<StyleShadowSVGData> { public: - static PassRefPtr<StyleMarkerData> create() { return adoptRef(new StyleMarkerData); } - PassRefPtr<StyleMarkerData> copy() const { return adoptRef(new StyleMarkerData(*this)); } + static PassRefPtr<StyleShadowSVGData> create() { return adoptRef(new StyleShadowSVGData); } + PassRefPtr<StyleShadowSVGData> copy() const { return adoptRef(new StyleShadowSVGData(*this)); } - bool operator==(const StyleMarkerData &other) const; - bool operator!=(const StyleMarkerData &other) const + bool operator==(const StyleShadowSVGData&) const; + bool operator!=(const StyleShadowSVGData& other) const { return !(*this == other); } - String startMarker; - String midMarker; - String endMarker; + OwnPtr<ShadowData> shadow; private: - StyleMarkerData(); - StyleMarkerData(const StyleMarkerData&); + StyleShadowSVGData(); + StyleShadowSVGData(const StyleShadowSVGData&); }; - // Note : the rule for this class is, *no inheritance* of these props - class StyleMiscData : public RefCounted<StyleMiscData> { + // Non-inherited resources + class StyleResourceData : public RefCounted<StyleResourceData> { public: - static PassRefPtr<StyleMiscData> create() { return adoptRef(new StyleMiscData); } - PassRefPtr<StyleMiscData> copy() const { return adoptRef(new StyleMiscData(*this)); } + static PassRefPtr<StyleResourceData> create() { return adoptRef(new StyleResourceData); } + PassRefPtr<StyleResourceData> copy() const { return adoptRef(new StyleResourceData(*this)); } - bool operator==(const StyleMiscData &other) const; - bool operator!=(const StyleMiscData &other) const + bool operator==(const StyleResourceData&) const; + bool operator!=(const StyleResourceData& other) const { return !(*this == other); } + String clipper; String filter; - Color floodColor; - float floodOpacity; - - Color lightingColor; - - // non-inherited text stuff lives here not in StyleTextData. - RefPtr<CSSValue> baselineShiftValue; + String masker; private: - StyleMiscData(); - StyleMiscData(const StyleMiscData&); + StyleResourceData(); + StyleResourceData(const StyleResourceData&); }; - - class StyleShadowSVGData : public RefCounted<StyleShadowSVGData> { + + // Inherited resources + class StyleInheritedResourceData : public RefCounted<StyleInheritedResourceData> { public: - static PassRefPtr<StyleShadowSVGData> create() { return adoptRef(new StyleShadowSVGData); } - PassRefPtr<StyleShadowSVGData> copy() const { return adoptRef(new StyleShadowSVGData(*this)); } - - bool operator==(const StyleShadowSVGData& other) const; - bool operator!=(const StyleShadowSVGData& other) const + static PassRefPtr<StyleInheritedResourceData> create() { return adoptRef(new StyleInheritedResourceData); } + PassRefPtr<StyleInheritedResourceData> copy() const { return adoptRef(new StyleInheritedResourceData(*this)); } + + bool operator==(const StyleInheritedResourceData&) const; + bool operator!=(const StyleInheritedResourceData& other) const { return !(*this == other); } - OwnPtr<ShadowData> shadow; + String markerStart; + String markerMid; + String markerEnd; private: - StyleShadowSVGData(); - StyleShadowSVGData(const StyleShadowSVGData& other); + StyleInheritedResourceData(); + StyleInheritedResourceData(const StyleInheritedResourceData&); }; } // namespace WebCore #endif // ENABLE(SVG) #endif // SVGRenderStyleDefs_h - -// vim:ts=4:noet diff --git a/WebCore/rendering/style/ShadowData.cpp b/WebCore/rendering/style/ShadowData.cpp index 1954224..d4569d0 100644 --- a/WebCore/rendering/style/ShadowData.cpp +++ b/WebCore/rendering/style/ShadowData.cpp @@ -25,23 +25,23 @@ namespace WebCore { ShadowData::ShadowData(const ShadowData& o) - : x(o.x) - , y(o.y) - , blur(o.blur) - , spread(o.spread) - , style(o.style) - , color(o.color) + : m_x(o.m_x) + , m_y(o.m_y) + , m_blur(o.m_blur) + , m_spread(o.m_spread) + , m_style(o.m_style) + , m_color(o.m_color) { - next = o.next ? new ShadowData(*o.next) : 0; + m_next = o.m_next ? new ShadowData(*o.m_next) : 0; } bool ShadowData::operator==(const ShadowData& o) const { - if ((next && !o.next) || (!next && o.next) || - (next && o.next && *next != *o.next)) + if ((m_next && !o.m_next) || (!m_next && o.m_next) || + (m_next && o.m_next && *m_next != *o.m_next)) return false; - return x == o.x && y == o.y && blur == o.blur && spread == o.spread && style == o.style && color == o.color; + return m_x == o.m_x && m_y == o.m_y && m_blur == o.m_blur && m_spread == o.m_spread && m_style == o.m_style && m_color == o.m_color; } } // namespace WebCore diff --git a/WebCore/rendering/style/ShadowData.h b/WebCore/rendering/style/ShadowData.h index 089cf77..9252e13 100644 --- a/WebCore/rendering/style/ShadowData.h +++ b/WebCore/rendering/style/ShadowData.h @@ -34,31 +34,31 @@ enum ShadowStyle { Normal, Inset }; // This struct holds information about shadows for the text-shadow and box-shadow properties. -struct ShadowData : FastAllocBase { +class ShadowData : public FastAllocBase { +public: ShadowData() - : x(0) - , y(0) - , blur(0) - , spread(0) - , style(Normal) - , next(0) + : m_x(0) + , m_y(0) + , m_blur(0) + , m_spread(0) + , m_style(Normal) + , m_next(0) { } ShadowData(int x, int y, int blur, int spread, ShadowStyle style, const Color& color) - : x(x) - , y(y) - , blur(blur) - , spread(spread) - , style(style) - , color(color) - , next(0) + : m_x(x) + , m_y(y) + , m_blur(blur) + , m_spread(spread) + , m_style(style) + , m_color(color) + , m_next(0) { } ShadowData(const ShadowData& o); - - ~ShadowData() { delete next; } + ~ShadowData() { delete m_next; } bool operator==(const ShadowData& o) const; bool operator!=(const ShadowData& o) const @@ -66,13 +66,24 @@ struct ShadowData : FastAllocBase { return !(*this == o); } - int x; - int y; - int blur; - int spread; - ShadowStyle style; - Color color; - ShadowData* next; + int x() const { return m_x; } + int y() const { return m_y; } + int blur() const { return m_blur; } + int spread() const { return m_spread; } + ShadowStyle style() const { return m_style; } + const Color& color() const { return m_color; } + + const ShadowData* next() const { return m_next; } + void setNext(ShadowData* shadow) { m_next = shadow; } + +private: + int m_x; + int m_y; + int m_blur; + int m_spread; + ShadowStyle m_style; + Color m_color; + ShadowData* m_next; }; } // namespace WebCore diff --git a/WebCore/rendering/style/StyleBackgroundData.h b/WebCore/rendering/style/StyleBackgroundData.h index 8f2da36..48a700e 100644 --- a/WebCore/rendering/style/StyleBackgroundData.h +++ b/WebCore/rendering/style/StyleBackgroundData.h @@ -45,13 +45,19 @@ public: return !(*this == o); } - FillLayer m_background; - Color m_color; - OutlineValue m_outline; + const FillLayer& background() const { return m_background; } + const Color& color() const { return m_color; } + const OutlineValue& outline() const { return m_outline; } private: + friend class RenderStyle; + StyleBackgroundData(); - StyleBackgroundData(const StyleBackgroundData&); + StyleBackgroundData(const StyleBackgroundData&); + + FillLayer m_background; + Color m_color; + OutlineValue m_outline; }; } // namespace WebCore diff --git a/WebCore/rendering/style/StyleBoxData.cpp b/WebCore/rendering/style/StyleBoxData.cpp index d9734d1..2c523da 100644 --- a/WebCore/rendering/style/StyleBoxData.cpp +++ b/WebCore/rendering/style/StyleBoxData.cpp @@ -28,40 +28,41 @@ namespace WebCore { StyleBoxData::StyleBoxData() - : z_index(0) - , z_auto(true) - , boxSizing(CONTENT_BOX) + : m_minWidth(RenderStyle::initialMinSize()) + , m_maxWidth(RenderStyle::initialMaxSize()) + , m_minHeight(RenderStyle::initialMinSize()) + , m_maxHeight(RenderStyle::initialMaxSize()) + , m_zIndex(0) + , m_hasAutoZIndex(true) + , m_boxSizing(CONTENT_BOX) { - // Initialize our min/max widths/heights. - min_width = min_height = RenderStyle::initialMinSize(); - max_width = max_height = RenderStyle::initialMaxSize(); } StyleBoxData::StyleBoxData(const StyleBoxData& o) : RefCounted<StyleBoxData>() - , width(o.width) - , height(o.height) - , min_width(o.min_width) - , max_width(o.max_width) - , min_height(o.min_height) - , max_height(o.max_height) - , z_index(o.z_index) - , z_auto(o.z_auto) - , boxSizing(o.boxSizing) + , m_width(o.m_width) + , m_height(o.m_height) + , m_minWidth(o.m_minWidth) + , m_maxWidth(o.m_maxWidth) + , m_minHeight(o.m_minHeight) + , m_maxHeight(o.m_maxHeight) + , m_zIndex(o.m_zIndex) + , m_hasAutoZIndex(o.m_hasAutoZIndex) + , m_boxSizing(o.m_boxSizing) { } bool StyleBoxData::operator==(const StyleBoxData& o) const { - return width == o.width && - height == o.height && - min_width == o.min_width && - max_width == o.max_width && - min_height == o.min_height && - max_height == o.max_height && - z_index == o.z_index && - z_auto == o.z_auto && - boxSizing == o.boxSizing; + return m_width == o.m_width + && m_height == o.m_height + && m_minWidth == o.m_minWidth + && m_maxWidth == o.m_maxWidth + && m_minHeight == o.m_minHeight + && m_maxHeight == o.m_maxHeight + && m_zIndex == o.m_zIndex + && m_hasAutoZIndex == o.m_hasAutoZIndex + && m_boxSizing == o.m_boxSizing; } } // namespace WebCore diff --git a/WebCore/rendering/style/StyleBoxData.h b/WebCore/rendering/style/StyleBoxData.h index a5bd2ff..00bce4e 100644 --- a/WebCore/rendering/style/StyleBoxData.h +++ b/WebCore/rendering/style/StyleBoxData.h @@ -26,6 +26,7 @@ #define StyleBoxData_h #include "Length.h" +#include "RenderStyleConstants.h" #include <wtf/RefCounted.h> #include <wtf/PassRefPtr.h> @@ -42,24 +43,42 @@ public: return !(*this == o); } - Length width; - Length height; - - Length min_width; - Length max_width; - - Length min_height; - Length max_height; - - Length vertical_align; - - int z_index; - bool z_auto : 1; - unsigned boxSizing : 1; // EBoxSizing + Length width() const { return m_width; } + Length height() const { return m_height; } + + Length minWidth() const { return m_minWidth; } + Length minHeight() const { return m_minHeight; } + + Length maxWidth() const { return m_maxWidth; } + Length maxHeight() const { return m_maxHeight; } + + Length verticalAlign() const { return m_verticalAlign; } + + int zIndex() const { return m_zIndex; } + bool hasAutoZIndex() const { return m_hasAutoZIndex; } + EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(m_boxSizing); } + private: + friend class RenderStyle; + StyleBoxData(); StyleBoxData(const StyleBoxData&); + + Length m_width; + Length m_height; + + Length m_minWidth; + Length m_maxWidth; + + Length m_minHeight; + Length m_maxHeight; + + Length m_verticalAlign; + + int m_zIndex; + bool m_hasAutoZIndex : 1; + unsigned m_boxSizing : 1; // EBoxSizing }; } // namespace WebCore diff --git a/WebCore/rendering/style/StyleMultiColData.h b/WebCore/rendering/style/StyleMultiColData.h index dec0a55..d3fe720 100644 --- a/WebCore/rendering/style/StyleMultiColData.h +++ b/WebCore/rendering/style/StyleMultiColData.h @@ -50,7 +50,7 @@ public: { if (m_rule.style() == BNONE || m_rule.style() == BHIDDEN) return 0; - return m_rule.width; + return m_rule.width(); } float m_width; |