diff options
Diffstat (limited to 'WebCore/rendering')
120 files changed, 2350 insertions, 755 deletions
diff --git a/WebCore/rendering/AutoTableLayout.h b/WebCore/rendering/AutoTableLayout.h index 641a68b..f1ef768 100644 --- a/WebCore/rendering/AutoTableLayout.h +++ b/WebCore/rendering/AutoTableLayout.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2002 Lars Knoll (knoll@kde.org) * (C) 2002 Dirk Mueller (mueller@kde.org) * diff --git a/WebCore/rendering/CounterNode.cpp b/WebCore/rendering/CounterNode.cpp index f546abb..95a3748 100644 --- a/WebCore/rendering/CounterNode.cpp +++ b/WebCore/rendering/CounterNode.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * @@ -46,7 +44,58 @@ CounterNode::CounterNode(RenderObject* o, bool isReset, int value) , m_nextSibling(0) , m_firstChild(0) , m_lastChild(0) -{ +{ +} + +CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const +{ + if (this == stayWithin) + return 0; + + CounterNode* next = m_nextSibling; + if (next) + return next; + next = m_parent; + while (next && !next->m_nextSibling) { + if (next == stayWithin) + return 0; + next = next->m_parent; + } + if (next) + return next->m_nextSibling; + return 0; +} + +CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const +{ + if (CounterNode* next = m_firstChild) + return next; + + return nextInPreOrderAfterChildren(stayWithin); +} + +CounterNode* CounterNode::lastDescendant() const +{ + CounterNode* last = m_lastChild; + if (!last) + return 0; + + while (CounterNode* lastChild = last->m_lastChild) + last = lastChild; + + return last; +} + +CounterNode* CounterNode::previousInPreOrder() const +{ + CounterNode* previous = m_previousSibling; + if (!previous) + return m_parent; + + while (CounterNode* lastChild = previous->m_lastChild) + previous = lastChild; + + return previous; } int CounterNode::computeCountInParent() const @@ -58,26 +107,37 @@ int CounterNode::computeCountInParent() const return m_parent->m_value + increment; } -void CounterNode::recount() + +void CounterNode::resetRenderer(const AtomicString& identifier) const +{ + if (!m_renderer || m_renderer->documentBeingDestroyed()) + return; + if (RenderObjectChildList* children = m_renderer->virtualChildren()) + children->invalidateCounters(m_renderer, identifier); +} + +void CounterNode::resetRenderers(const AtomicString& identifier) const +{ + const CounterNode* node = this; + do { + node->resetRenderer(identifier); + node = node->nextInPreOrder(this); + } while (node); +} + +void CounterNode::recount(const AtomicString& identifier) { - for (CounterNode* c = this; c; c = c->m_nextSibling) { - int oldCount = c->m_countInParent; - int newCount = c->computeCountInParent(); + for (CounterNode* node = this; node; node = node->m_nextSibling) { + int oldCount = node->m_countInParent; + int newCount = node->computeCountInParent(); if (oldCount == newCount) break; - c->m_countInParent = newCount; - // m_renderer contains the parent of the render node - // corresponding to a CounterNode. Let's find the counter - // child and make this re-layout. - for (RenderObject* o = c->m_renderer->firstChild(); o; o = o->nextSibling()) - if (!o->documentBeingDestroyed() && o->isCounter()) { - o->setNeedsLayoutAndPrefWidthsRecalc(); - break; - } + node->m_countInParent = newCount; + node->resetRenderers(identifier); } } -void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild) +void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, const AtomicString& identifier) { ASSERT(newChild); ASSERT(!newChild->m_parent); @@ -109,77 +169,56 @@ void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild) newChild->m_countInParent = newChild->computeCountInParent(); if (next) - next->recount(); + next->recount(identifier); } -void CounterNode::removeChild(CounterNode* oldChild) +void CounterNode::removeChild(CounterNode* oldChild, const AtomicString& identifier) { ASSERT(oldChild); ASSERT(!oldChild->m_firstChild); ASSERT(!oldChild->m_lastChild); CounterNode* next = oldChild->m_nextSibling; - CounterNode* prev = oldChild->m_previousSibling; + CounterNode* previous = oldChild->m_previousSibling; oldChild->m_nextSibling = 0; oldChild->m_previousSibling = 0; oldChild->m_parent = 0; - if (prev) - prev->m_nextSibling = next; + if (previous) + previous->m_nextSibling = next; else { ASSERT(m_firstChild == oldChild); m_firstChild = next; } - + if (next) - next->m_previousSibling = prev; + next->m_previousSibling = previous; else { ASSERT(m_lastChild == oldChild); - m_lastChild = prev; + m_lastChild = previous; } - + if (next) - next->recount(); + next->recount(identifier); } #ifndef NDEBUG -static const CounterNode* nextInPreOrderAfterChildren(const CounterNode* node) -{ - CounterNode* next = node->nextSibling(); - if (!next) { - next = node->parent(); - while (next && !next->nextSibling()) - next = next->parent(); - if (next) - next = next->nextSibling(); - } - return next; -} - -static const CounterNode* nextInPreOrder(const CounterNode* node) -{ - if (CounterNode* child = node->firstChild()) - return child; - return nextInPreOrderAfterChildren(node); -} - static void showTreeAndMark(const CounterNode* node) { const CounterNode* root = node; while (root->parent()) root = root->parent(); - for (const CounterNode* c = root; c; c = nextInPreOrder(c)) { - if (c == node) - fprintf(stderr, "*"); - for (const CounterNode* d = c; d && d != root; d = d->parent()) - fprintf(stderr, "\t"); - if (c->isReset()) - fprintf(stderr, "reset: %d %d\n", c->value(), c->countInParent()); - else - fprintf(stderr, "increment: %d %d\n", c->value(), c->countInParent()); + for (const CounterNode* current = root; current; current = current->nextInPreOrder()) { + fwrite((current == node) ? "*" : " ", 1, 1, stderr); + for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent()) + fwrite(" ", 1, 2, stderr); + fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n", + current, current->isReset() ? "reset____" : "increment", current->value(), + current->countInParent(), current->parent(), current->previousSibling(), + current->nextSibling(), current->renderer()); } } diff --git a/WebCore/rendering/CounterNode.h b/WebCore/rendering/CounterNode.h index b432e1d..8081dc6 100644 --- a/WebCore/rendering/CounterNode.h +++ b/WebCore/rendering/CounterNode.h @@ -35,6 +35,7 @@ namespace WebCore { +class AtomicString; class RenderObject; class CounterNode : public Noncopyable { @@ -51,13 +52,19 @@ public: CounterNode* nextSibling() const { return m_nextSibling; } CounterNode* firstChild() const { return m_firstChild; } CounterNode* lastChild() const { return m_lastChild; } + CounterNode* lastDescendant() const; + CounterNode* previousInPreOrder() const; + CounterNode* nextInPreOrder(const CounterNode* stayWithin = 0) const; + CounterNode* nextInPreOrderAfterChildren(const CounterNode* stayWithin = 0) const; - void insertAfter(CounterNode* newChild, CounterNode* beforeChild); - void removeChild(CounterNode*); + void insertAfter(CounterNode* newChild, CounterNode* beforeChild, const AtomicString& identifier); + void removeChild(CounterNode*, const AtomicString& identifier); private: int computeCountInParent() const; - void recount(); + void recount(const AtomicString& identifier); + void resetRenderer(const AtomicString& identifier) const; + void resetRenderers(const AtomicString& identifier) const; bool m_isReset; int m_value; diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp index db9a101..bea9d73 100644 --- a/WebCore/rendering/EllipsisBox.cpp +++ b/WebCore/rendering/EllipsisBox.cpp @@ -1,6 +1,4 @@ /** -* This file is part of the html renderer for KDE. - * * Copyright (C) 2003, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or @@ -34,11 +32,11 @@ void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) RenderStyle* style = m_renderer->style(m_firstLine); Color textColor = style->color(); if (textColor != context->fillColor()) - context->setFillColor(textColor); + 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->textShadow()->blur, style->textShadow()->color, style->colorSpace()); setShadow = true; } diff --git a/WebCore/rendering/EllipsisBox.h b/WebCore/rendering/EllipsisBox.h index 9dbd27f..a228d7a 100644 --- a/WebCore/rendering/EllipsisBox.h +++ b/WebCore/rendering/EllipsisBox.h @@ -1,6 +1,4 @@ /** -* This file is part of the html renderer for KDE. - * * Copyright (C) 2003, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp index 4852708..09af518 100644 --- a/WebCore/rendering/FixedTableLayout.cpp +++ b/WebCore/rendering/FixedTableLayout.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2002 Lars Knoll (knoll@kde.org) * (C) 2002 Dirk Mueller (mueller@kde.org) * Copyright (C) 2003, 2006 Apple Computer, Inc. diff --git a/WebCore/rendering/FixedTableLayout.h b/WebCore/rendering/FixedTableLayout.h index ed7c089..758ddbb 100644 --- a/WebCore/rendering/FixedTableLayout.h +++ b/WebCore/rendering/FixedTableLayout.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2002 Lars Knoll (knoll@kde.org) * (C) 2002 Dirk Mueller (mueller@kde.org) * diff --git a/WebCore/rendering/HitTestRequest.h b/WebCore/rendering/HitTestRequest.h index 46dd7b8..ca1445a 100644 --- a/WebCore/rendering/HitTestRequest.h +++ b/WebCore/rendering/HitTestRequest.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ * diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h index 25e1058..d1906ba 100644 --- a/WebCore/rendering/HitTestResult.h +++ b/WebCore/rendering/HitTestResult.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index baea956..2bd1683 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -974,6 +974,7 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int setClip = true; } + ColorSpace colorSpace = renderer()->style()->colorSpace(); bool setShadow = false; do { if (shadow) { @@ -982,24 +983,24 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int ty -= extraOffset; extraOffset = 0; } - context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color); + context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color, colorSpace); setShadow = true; shadow = shadow->next; } if (paintUnderline) { - context->setStrokeColor(underline); + context->setStrokeColor(underline, colorSpace); context->setStrokeStyle(SolidStroke); // Leave one pixel of white between the baseline and the underline. context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting); } if (paintOverline) { - context->setStrokeColor(overline); + context->setStrokeColor(overline, colorSpace); context->setStrokeStyle(SolidStroke); context->drawLineForText(IntPoint(tx, ty), w, isPrinting); } if (paintLineThrough) { - context->setStrokeColor(linethrough); + context->setStrokeColor(linethrough, colorSpace); context->setStrokeStyle(SolidStroke); context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting); } diff --git a/WebCore/rendering/InlineRunBox.h b/WebCore/rendering/InlineRunBox.h index 0f7c29b..cbc82d5 100644 --- a/WebCore/rendering/InlineRunBox.h +++ b/WebCore/rendering/InlineRunBox.h @@ -1,6 +1,4 @@ /* - * This file is part of the line box implementation for KDE. - * * Copyright (C) 2003, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 751340d..31e6967 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -214,7 +214,7 @@ Color correctedTextColor(Color textColor, Color backgroundColor) return textColor.light(); } -void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness) +void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace colorSpace) { int mode = context->textDrawingMode(); if (strokeThickness > 0) { @@ -225,12 +225,12 @@ void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, con } } - if (mode & cTextFill && fillColor != context->fillColor()) - context->setFillColor(fillColor); + if (mode & cTextFill && (fillColor != context->fillColor() || colorSpace != context->fillColorSpace())) + context->setFillColor(fillColor, colorSpace); if (mode & cTextStroke) { if (strokeColor != context->strokeColor()) - context->setStrokeColor(strokeColor); + context->setStrokeColor(strokeColor, colorSpace); if (strokeThickness != context->strokeThickness()) context->setStrokeThickness(strokeThickness); } @@ -257,9 +257,10 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked) { Color fillColor = context->fillColor(); + ColorSpace fillColorSpace = context->fillColorSpace(); bool opaque = fillColor.alpha() == 255; if (!opaque) - context->setFillColor(Color::black); + context->setFillColor(Color::black, fillColorSpace); do { IntSize extraOffset; @@ -279,9 +280,9 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con extraOffset = IntSize(0, 2 * h + max(0, shadowOffset.height()) + shadowBlur); shadowOffset -= extraOffset; } - context->setShadow(shadowOffset, shadowBlur, shadowColor); + context->setShadow(shadowOffset, shadowBlur, shadowColor, fillColorSpace); } else if (!opaque) - context->setFillColor(fillColor); + context->setFillColor(fillColor, fillColorSpace); if (startOffset <= endOffset) context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset); @@ -465,7 +466,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) if (textStrokeWidth > 0) context->save(); - updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth); + updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace()); if (!paintSelectedTextSeparately || ePos <= sPos) { // FIXME: Truncate right-to-left text correctly. paintTextWithShadows(context, font, textRun, 0, m_truncation == cNoTruncation ? m_len : m_truncation, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0); @@ -481,7 +482,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) if (selectionStrokeWidth > 0) context->save(); - updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth); + updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, styleToUse->colorSpace()); paintTextWithShadows(context, font, textRun, sPos, ePos, textOrigin, m_x + tx, m_y + ty, width(), height(), selectionShadow, selectionStrokeWidth > 0); if (selectionStrokeWidth > 0) @@ -490,7 +491,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()); + context->setStrokeColor(styleToUse->color(), styleToUse->colorSpace()); paintDecoration(context, tx, ty, d, textShadow); } @@ -561,13 +562,13 @@ void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, Ren c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); context->save(); - updateGraphicsContext(context, c, c, 0); // Don't draw text at all! + updateGraphicsContext(context, c, c, 0, style->colorSpace()); // Don't draw text at all! int y = selectionTop(); int h = selectionHeight(); context->clip(IntRect(m_x + tx, y + ty, m_width, h)); context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), - IntPoint(m_x + tx, y + ty), h, c, sPos, ePos); + IntPoint(m_x + tx, y + ty), h, c, style->colorSpace(), sPos, ePos); context->restore(); } @@ -584,13 +585,13 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, Color c = Color(225, 221, 85); - updateGraphicsContext(context, c, c, 0); // Don't draw text at all! + updateGraphicsContext(context, c, c, 0, style->colorSpace()); // Don't draw text at all! int y = selectionTop(); int h = selectionHeight(); context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), - IntPoint(m_x + tx, y + ty), h, c, sPos, ePos); + IntPoint(m_x + tx, y + ty), h, c, style->colorSpace(), sPos, ePos); context->restore(); } @@ -660,6 +661,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in setClip = true; } + ColorSpace colorSpace = renderer()->style()->colorSpace(); bool setShadow = false; do { @@ -669,24 +671,24 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in ty -= extraOffset; extraOffset = 0; } - context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color); + context->setShadow(IntSize(shadow->x, shadow->y - extraOffset), shadow->blur, shadow->color, colorSpace); setShadow = true; shadow = shadow->next; } if (deco & UNDERLINE) { - context->setStrokeColor(underline); + context->setStrokeColor(underline, colorSpace); context->setStrokeStyle(SolidStroke); // Leave one pixel of white between the baseline and the underline. context->drawLineForText(IntPoint(tx, ty + baseline + 1), width, isPrinting); } if (deco & OVERLINE) { - context->setStrokeColor(overline); + context->setStrokeColor(overline, colorSpace); context->setStrokeStyle(SolidStroke); context->drawLineForText(IntPoint(tx, ty), width, isPrinting); } if (deco & LINE_THROUGH) { - context->setStrokeColor(linethrough); + context->setStrokeColor(linethrough, colorSpace); context->setStrokeStyle(SolidStroke); context->drawLineForText(IntPoint(tx, ty + 2 * baseline / 3), width, isPrinting); } @@ -698,7 +700,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in context->clearShadow(); } -void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font, bool grammar) +void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, const DocumentMarker& marker, RenderStyle* style, const Font& font, bool grammar) { // Never print spelling/grammar markers (5327887) if (textRenderer()->document()->printing()) @@ -737,8 +739,11 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to // display a toolTip. We don't do this for misspelling markers. - if (grammar) + if (grammar) { + markerRect.move(-tx, -ty); + markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); + } } // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to @@ -761,7 +766,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in pt->drawLineForMisspellingOrBadGrammar(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, grammar); } -void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font) +void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, const DocumentMarker& marker, RenderStyle* style, const Font& font) { // Use same y positioning and height as for selection, so that when the selection and this highlight are on // the same word there are no pieces sticking out. @@ -771,10 +776,10 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do int sPos = max(marker.startOffset - m_start, (unsigned)0); int ePos = min(marker.endOffset - m_start, (unsigned)m_len); TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()); - IntPoint startPoint = IntPoint(m_x + tx, y + ty); - // Always compute and store the rect associated with this marker - IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos)); + // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates. + IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(m_x, y), h, sPos, ePos)); + markerRect = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); // Optionally highlight the text @@ -783,14 +788,14 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do renderer()->theme()->platformActiveTextSearchHighlightColor() : renderer()->theme()->platformInactiveTextSearchHighlightColor(); pt->save(); - updateGraphicsContext(pt, color, color, 0); // Don't draw text at all! + updateGraphicsContext(pt, color, color, 0, style->colorSpace()); // Don't draw text at all! pt->clip(IntRect(tx + m_x, ty + y, m_width, h)); - pt->drawHighlightForText(font, run, startPoint, h, color, sPos, ePos); + pt->drawHighlightForText(font, run, IntPoint(m_x + tx, y + ty), h, color, style->colorSpace(), sPos, ePos); pt->restore(); } } -void InlineTextBox::computeRectForReplacementMarker(int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font) +void InlineTextBox::computeRectForReplacementMarker(int /*tx*/, int /*ty*/, const DocumentMarker& marker, RenderStyle* style, const Font& font) { // Replacement markers are not actually drawn, but their rects need to be computed for hit testing. int y = selectionTop(); @@ -799,10 +804,11 @@ void InlineTextBox::computeRectForReplacementMarker(int tx, int ty, DocumentMark int sPos = max(marker.startOffset - m_start, (unsigned)0); int ePos = min(marker.endOffset - m_start, (unsigned)m_len); TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()); - IntPoint startPoint = IntPoint(m_x + tx, y + ty); + IntPoint startPoint = IntPoint(m_x, y); // Compute and store the rect associated with this marker. IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos)); + markerRect = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); } @@ -817,7 +823,7 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re // Give any document markers that touch this run a chance to draw before the text has been drawn. // Note end() points at the last char, not one past it like endOffset and ranges do. for ( ; markerIt != markers.end(); markerIt++) { - DocumentMarker marker = *markerIt; + const DocumentMarker& marker = *markerIt; // Paint either the background markers or the foreground markers, but not both switch (marker.type) { @@ -911,7 +917,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int start += 1; width -= 2; - ctx->setStrokeColor(underline.color); + ctx->setStrokeColor(underline.color, renderer()->style()->colorSpace()); ctx->setStrokeThickness(lineThickness); ctx->drawLineForText(IntPoint(tx + start, ty + height() - lineThickness), width, textRenderer()->document()->printing()); } @@ -936,7 +942,7 @@ int InlineTextBox::textPos() const if (x() == 0) return 0; - RenderBlock *blockElement = renderer()->containingBlock(); + RenderBlock* blockElement = renderer()->containingBlock(); return direction() == RTL ? x() - blockElement->borderRight() - blockElement->paddingRight() : x() - blockElement->borderLeft() - blockElement->paddingLeft(); } @@ -947,7 +953,7 @@ int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const return 0; RenderText* text = toRenderText(renderer()); - RenderStyle *style = text->style(m_firstLine); + RenderStyle* style = text->style(m_firstLine); const Font* f = &style->font(); return f->offsetForPosition(TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), _x - m_x, includePartialGlyphs); diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index 3bbb453..80af2e3 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -34,7 +34,7 @@ const unsigned short cNoTruncation = USHRT_MAX; const unsigned short cFullTruncation = USHRT_MAX - 1; // Helper functions shared by InlineTextBox / SVGRootInlineBox -void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness); +void updateGraphicsContext(GraphicsContext*, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace); Color correctedTextColor(Color textColor, Color backgroundColor); class InlineTextBox : public InlineRunBox { @@ -131,9 +131,9 @@ protected: private: void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, ShadowData*); void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&); - void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font&, bool grammar); - void paintTextMatchMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font&); - void computeRectForReplacementMarker(int tx, int ty, DocumentMarker, 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&); + void computeRectForReplacementMarker(int tx, int ty, const DocumentMarker&, RenderStyle*, const Font&); }; inline RenderText* InlineTextBox::textRenderer() const diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 9611660..9c56756 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -38,6 +38,7 @@ #include "HTMLNames.h" #include "LocalizedStrings.h" #include "MouseEvent.h" +#include "Page.h" #include "RenderMedia.h" #include "RenderSlider.h" #include "RenderTheme.h" @@ -347,6 +348,9 @@ MediaControlInputElement::MediaControlInputElement(Document* document, PseudoId case MEDIA_CONTROLS_VOLUME_SLIDER: m_displayType = MediaVolumeSlider; break; + case MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON: + m_displayType = MediaShowClosedCaptionsButton; + break; default: ASSERT_NOT_REACHED(); break; @@ -577,6 +581,29 @@ void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event // ---------------------------- +MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document* doc, HTMLMediaElement* element) + : MediaControlInputElement(doc, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON, "button", element) +{ +} + +void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().clickEvent) { + m_mediaElement->setClosedCaptionsVisible(!m_mediaElement->closedCaptionsVisible()); + setChecked(m_mediaElement->closedCaptionsVisible()); + event->setDefaultHandled(); + } + HTMLInputElement::defaultEventHandler(event); +} + +void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() +{ + setDisplayType(m_mediaElement->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton); +} + + +// ---------------------------- + MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element) : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element) { @@ -649,10 +676,9 @@ void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) void MediaControlVolumeSliderElement::update() { float volume = m_mediaElement->volume(); - if (value().toFloat() != volume) { + if (value().toFloat() != volume) setValue(String::number(volume)); - MediaControlInputElement::update(); - } + MediaControlInputElement::update(); } // ---------------------------- diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h index 8b29773..0ba4aba 100644 --- a/WebCore/rendering/MediaControlElements.h +++ b/WebCore/rendering/MediaControlElements.h @@ -54,6 +54,8 @@ enum MediaControlElementType { MediaSliderThumb, MediaRewindButton, MediaReturnToRealtimeButton, + MediaShowClosedCaptionsButton, + MediaHideClosedCaptionsButton, MediaUnMuteButton, MediaPauseButton, MediaTimelineContainer, @@ -221,6 +223,15 @@ public: // ---------------------------- +class MediaControlToggleClosedCaptionsButtonElement : public MediaControlInputElement { +public: + MediaControlToggleClosedCaptionsButtonElement(Document*, HTMLMediaElement*); + virtual void defaultEventHandler(Event*); + virtual void updateDisplayType(); +}; + +// ---------------------------- + class MediaControlTimelineElement : public MediaControlInputElement { public: MediaControlTimelineElement(Document*, HTMLMediaElement*); diff --git a/WebCore/rendering/PointerEventsHitRules.cpp b/WebCore/rendering/PointerEventsHitRules.cpp index 214fb09..ababcfd 100644 --- a/WebCore/rendering/PointerEventsHitRules.cpp +++ b/WebCore/rendering/PointerEventsHitRules.cpp @@ -1,8 +1,6 @@ /* Copyright (C) 2007 Rob Buis <buis@kde.org> - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/PointerEventsHitRules.h b/WebCore/rendering/PointerEventsHitRules.h index 3d8939a..c17c19c 100644 --- a/WebCore/rendering/PointerEventsHitRules.h +++ b/WebCore/rendering/PointerEventsHitRules.h @@ -1,8 +1,6 @@ /* Copyright (C) 2007 Rob Buis <buis@kde.org> - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/RenderArena.h b/WebCore/rendering/RenderArena.h index ca35361..edf052a 100644 --- a/WebCore/rendering/RenderArena.h +++ b/WebCore/rendering/RenderArena.h @@ -36,12 +36,13 @@ #define RenderArena_h #include "Arena.h" +#include <wtf/Noncopyable.h> namespace WebCore { static const size_t gMaxRecycledSize = 400; -class RenderArena { +class RenderArena : public Noncopyable { public: RenderArena(unsigned arenaSize = 4096); ~RenderArena(); diff --git a/WebCore/rendering/RenderBR.cpp b/WebCore/rendering/RenderBR.cpp index e05c8b4..012a433 100644 --- a/WebCore/rendering/RenderBR.cpp +++ b/WebCore/rendering/RenderBR.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * Copyright (C) 2006 Apple Computer, Inc. * diff --git a/WebCore/rendering/RenderBR.h b/WebCore/rendering/RenderBR.h index 7eae8ea..8850d46 100644 --- a/WebCore/rendering/RenderBR.h +++ b/WebCore/rendering/RenderBR.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 7040e06..204a0c3 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -44,6 +44,7 @@ #include "RenderView.h" #include "SelectionController.h" #include "Settings.h" +#include "TransformState.h" #include <wtf/StdLibExtras.h> #ifdef ANDROID_LAYOUT @@ -62,13 +63,7 @@ static const int verticalLineClickFudgeFactor = 3; using namespace HTMLNames; -static void moveChild(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* from, RenderObjectChildList* fromChildList, RenderObject* child) -{ - ASSERT(from == child->parent()); - toChildList->appendChildNode(to, fromChildList->removeChildNode(from, child, false), false); -} - -struct ColumnInfo { +struct ColumnInfo : public Noncopyable { ColumnInfo() : m_desiredColumnWidth(0) , m_desiredColumnCount(1) @@ -167,6 +162,7 @@ RenderBlock::~RenderBlock() void RenderBlock::destroy() { +<<<<<<< HEAD:WebCore/rendering/RenderBlock.cpp // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise. children()->destroyLeftoverChildren(); @@ -178,7 +174,20 @@ void RenderBlock::destroy() m_inlineContinuation->destroy(); m_inlineContinuation = 0; } +======= + // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will + // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise. + children()->destroyLeftoverChildren(); +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderBlock.cpp + // Destroy our continuation before anything other than anonymous children. + // The reason we don't destroy it before anonymous children is that they may + // have continuations of their own that are anonymous children of our continuation. + if (m_inlineContinuation) { + m_inlineContinuation->destroy(); + m_inlineContinuation = 0; + } + if (!documentBeingDestroyed()) { if (firstLineBox()) { // We can't wait for RenderBox::destroy to clear the selection, @@ -406,6 +415,19 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox() m_lineBoxes.appendLineBox(rootBox); return rootBox; } + +void RenderBlock::moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child) +{ + ASSERT(this == child->parent()); + toChildList->appendChildNode(to, children()->removeChildNode(this, child, false), false); +} + +void RenderBlock::moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child) +{ + ASSERT(this == child->parent()); + ASSERT(!beforeChild || to == beforeChild->parent()); + toChildList->insertChildNode(to, children()->removeChildNode(this, child, false), beforeChild, false); +} void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint) { @@ -443,9 +465,9 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint) RenderObject* no = o; o = no->nextSibling(); - moveChild(block, block->children(), this, children(), no); + moveChildTo(block, block->children(), no); } - moveChild(block, block->children(), this, children(), inlineRunEnd); + moveChildTo(block, block->children(), inlineRunEnd); } #ifndef NDEBUG @@ -520,7 +542,7 @@ void RenderBlock::removeChild(RenderObject* oldChild) while (o) { RenderObject* no = o; o = no->nextSibling(); - moveChild(prevBlock, prevBlock->children(), nextBlock, nextBlock->children(), no); + nextBlock->moveChildTo(prevBlock, prevBlock->children(), no); } nextBlock->deleteLineBoxTree(); @@ -543,7 +565,7 @@ void RenderBlock::removeChild(RenderObject* oldChild) while (o) { RenderObject* no = o; o = no->nextSibling(); - moveChild(this, children(), anonBlock, anonBlock->children(), no); + anonBlock->moveChildTo(this, children(), no); } // Delete the now-empty block's lines and nuke it. @@ -613,15 +635,15 @@ void RenderBlock::finishDelayUpdateScrollInfo() if (gDelayUpdateScrollInfo == 0) { ASSERT(gDelayedUpdateScrollInfoSet); - for (DelayedUpdateScrollInfoSet::iterator it = gDelayedUpdateScrollInfoSet->begin(); it != gDelayedUpdateScrollInfoSet->end(); ++it) { + OwnPtr<DelayedUpdateScrollInfoSet> infoSet(gDelayedUpdateScrollInfoSet); + gDelayedUpdateScrollInfoSet = 0; + + for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) { RenderBlock* block = *it; if (block->hasOverflowClip()) { block->layer()->updateScrollInfoAfterLayout(); } } - - delete gDelayedUpdateScrollInfoSet; - gDelayedUpdateScrollInfoSet = 0; } } @@ -876,7 +898,11 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg } y += (collapsedTopPos - collapsedTopNeg) - marginTop; } - child->layer()->setStaticY(y); + RenderLayer* childLayer = child->layer(); + if (childLayer->staticY() != y) { + child->layer()->setStaticY(y); + child->setChildNeedsLayout(true, false); + } } } @@ -965,7 +991,7 @@ bool RenderBlock::handleRunInChild(RenderBox* child) // Move the nodes from the old child to the new child, but skip any :before/:after content. It has already // been regenerated by the new inline. for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild; runInChild = runInChild->nextSibling()) { - if (runInIsGenerated || runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER) { + if (runInIsGenerated || (runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER)) { blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false); inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content. } @@ -1535,7 +1561,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty) // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with // z-index. We paint after we painted the background/border, so that the scrollbars will // sit above the background/border. - if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground)) + if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && shouldPaintWithinRoot(paintInfo)) layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect); } @@ -1919,23 +1945,28 @@ bool RenderBlock::isSelectionRoot() const return false; } -GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* /*repaintContainer*/) +GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer) { ASSERT(!needsLayout()); if (!shouldPaintSelectionGaps()) return GapRects(); - // FIXME: this is broken with transforms and a non-null repaintContainer - FloatPoint absContentPoint = localToAbsolute(FloatPoint()); + // 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(); + if (hasOverflowClip()) - absContentPoint -= layer()->scrolledContentOffset(); + layer()->subtractScrolledContentOffset(x, y); int lastTop = 0; int lastLeft = leftSelectionOffset(this, lastTop); int lastRight = rightSelectionOffset(this, lastTop); - return fillSelectionGaps(this, absContentPoint.x(), absContentPoint.y(), absContentPoint.x(), absContentPoint.y(), lastTop, lastLeft, lastRight); + return fillSelectionGaps(this, x, y, x, y, lastTop, lastLeft, lastRight); } void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) @@ -1945,7 +1976,14 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) int lastLeft = leftSelectionOffset(this, lastTop); int lastRight = rightSelectionOffset(this, lastTop); paintInfo.context->save(); - fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &paintInfo); + IntRect gapRectsBounds = fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &paintInfo); + if (!gapRectsBounds.isEmpty()) { + if (RenderLayer* layer = enclosingLayer()) { + IntSize offset = hasLayer() ? IntSize() : offsetFromAncestorContainer(layer->renderer()); + gapRectsBounds.move(offset - IntSize(tx, ty)); + layer->addBlockSelectionGapsBounds(gapRectsBounds); + } + } paintInfo.context->restore(); } } @@ -2132,7 +2170,7 @@ IntRect RenderBlock::fillHorizontalSelectionGap(RenderObject* selObj, int xPos, return IntRect(); IntRect gapRect(xPos, yPos, width, height); if (paintInfo && selObj->style()->visibility() == VISIBLE) - paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor()); + paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); return gapRect; } @@ -2153,7 +2191,7 @@ IntRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int las IntRect gapRect(left, top, width, height); if (paintInfo) - paintInfo->context->fillRect(gapRect, selectionBackgroundColor()); + paintInfo->context->fillRect(gapRect, selectionBackgroundColor(), style()->colorSpace()); return gapRect; } @@ -2169,7 +2207,7 @@ IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yP IntRect gapRect(left, top, width, height); if (paintInfo) - paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor()); + paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); return gapRect; } @@ -2185,7 +2223,7 @@ IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int y IntRect gapRect(left, top, width, height); if (paintInfo) - paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor()); + paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace()); return gapRect; } @@ -3418,7 +3456,7 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& RootInlineBox* firstRootBoxWithChildren = 0; RootInlineBox* lastRootBoxWithChildren = 0; for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) { - if (!root->firstChild()) + if (!root->firstLeafChild()) continue; if (!firstRootBoxWithChildren) firstRootBoxWithChildren = root; @@ -3565,11 +3603,15 @@ void RenderBlock::calcColumnWidth() desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount; } else if (colGap < availWidth) { desiredColumnCount = availWidth / colGap; + if (desiredColumnCount < 1) + desiredColumnCount = 1; desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount; } } else if (style()->hasAutoColumnCount()) { if (colWidth < availWidth) { desiredColumnCount = (availWidth + colGap) / (colWidth + colGap); + if (desiredColumnCount < 1) + desiredColumnCount = 1; desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount; } } else { @@ -3579,6 +3621,8 @@ void RenderBlock::calcColumnWidth() desiredColumnWidth = colWidth; } else if (colWidth < availWidth) { desiredColumnCount = (availWidth + colGap) / (colWidth + colGap); + if (desiredColumnCount < 1) + desiredColumnCount = 1; desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount; } } @@ -3629,7 +3673,7 @@ Vector<IntRect>* RenderBlock::columnRects() const return &gColumnInfoMap->get(this)->m_columnRects; } -int RenderBlock::layoutColumns(int endOfContent) +int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight) { // Don't do anything if we have no columns if (!hasColumns()) @@ -3642,17 +3686,20 @@ int RenderBlock::layoutColumns(int endOfContent) bool computeIntrinsicHeight = (endOfContent == -1); - // Fill the columns in to the available height. Attempt to balance the height of the columns - int availableHeight = contentHeight(); - int colHeight = computeIntrinsicHeight ? availableHeight / desiredColumnCount : availableHeight; - + // Fill the columns in to the available height. Attempt to balance the height of the columns. // Add in half our line-height to help with best-guess initial balancing. int columnSlop = lineHeight(false) / 2; int remainingSlopSpace = columnSlop * desiredColumnCount; + int availableHeight = contentHeight(); + int colHeight; + if (computeIntrinsicHeight && requestedColumnHeight >= 0) + colHeight = requestedColumnHeight; + else if (computeIntrinsicHeight) + colHeight = availableHeight / desiredColumnCount + columnSlop; + else + colHeight = availableHeight; + int originalColHeight = colHeight; - if (computeIntrinsicHeight) - colHeight += columnSlop; - int colGap = columnGap(); // Compute a collection of column rects. @@ -3668,7 +3715,8 @@ int RenderBlock::layoutColumns(int endOfContent) int currY = top; unsigned colCount = desiredColumnCount; int maxColBottom = borderTop() + paddingTop(); - int contentBottom = top + availableHeight; + int contentBottom = top + availableHeight; + int minimumColumnHeight = -1; for (unsigned i = 0; i < colCount; i++) { // If we aren't constrained, then the last column can just get all the remaining space. if (computeIntrinsicHeight && i == colCount - 1) @@ -3688,6 +3736,11 @@ int RenderBlock::layoutColumns(int endOfContent) paintObject(paintInfo, 0, 0); setHasColumns(true); + if (computeIntrinsicHeight && v->minimumColumnHeight() > originalColHeight) { + // The initial column height was too small to contain one line of text. + minimumColumnHeight = max(minimumColumnHeight, v->minimumColumnHeight()); + } + int adjustedBottom = v->bestTruncatedAt(); if (adjustedBottom <= currY) adjustedBottom = currY + colHeight; @@ -3724,6 +3777,11 @@ int RenderBlock::layoutColumns(int endOfContent) colCount++; } + if (minimumColumnHeight >= 0) { + // If originalColHeight was too small, we need to try to layout again. + return layoutColumns(endOfContent, minimumColumnHeight); + } + int overflowRight = max(width(), currX - colGap); int overflowLeft = min(0, currX + desiredColumnWidth + colGap); int overflowHeight = maxColBottom; @@ -4208,6 +4266,10 @@ void RenderBlock::calcInlinePrefWidths() } else inlineMax += childMax; } + + // Ignore spaces after a list marker. + if (child->isListMarker()) + stripFrontSpaces = true; } else { m_minPrefWidth = max(inlineMin, m_minPrefWidth); m_maxPrefWidth = max(inlineMax, m_maxPrefWidth); diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index 1628701..985074d 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -140,6 +140,9 @@ public: RenderBlock* createAnonymousBlock(bool isFlexibleBox = false) const; protected: + void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child); + void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child); + int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); } int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); } int maxBottomPosMargin() const { return m_maxMargin ? m_maxMargin->m_bottomPos : MaxMargin::bottomPosDefault(this); } @@ -377,13 +380,13 @@ private: void offsetForContents(int& tx, int& ty) const; void calcColumnWidth(); - int layoutColumns(int endOfContent = -1); + int layoutColumns(int endOfContent = -1, int requestedColumnHeight = -1); bool expandsToEncloseOverhangingFloats() const; void updateScrollInfoAfterLayout(); - struct FloatingObject { + struct FloatingObject : Noncopyable { enum Type { FloatLeft, FloatRight @@ -499,7 +502,7 @@ private: RenderInline* m_inlineContinuation; // Allocated only when some of these fields have non-default values - struct MaxMargin { + struct MaxMargin : Noncopyable { MaxMargin(const RenderBlock* o) : m_topPos(topPosDefault(o)) , m_topNeg(topNegDefault(o)) diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index cf6514e..8517d6d 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -1869,10 +1869,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool currentCharacterIsSpace = false; currentCharacterIsWS = false; trailingSpaceObject = 0; - + // Optimize for a common case. If we can't find whitespace after the list // item, then this is all moot. -dwh - if (o->isListMarker() && !toRenderListMarker(o)->isInside()) { + if (o->isListMarker()) { if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) { // Like with inline flows, we start ignoring spaces to make sure that any // additional spaces we see will be discarded. @@ -1880,6 +1880,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool currentCharacterIsWS = true; ignoringSpaces = true; } + if (toRenderListMarker(o)->isInside()) + tmpW += replacedBox->width() + replacedBox->marginLeft() + replacedBox->marginRight() + inlineWidth(o); } else tmpW += replacedBox->width() + replacedBox->marginLeft() + replacedBox->marginRight() + inlineWidth(o); } else if (o->isText()) { diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 8e0f3b7..a7c2e63 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -1523,7 +1523,7 @@ void RenderBox::calcHeight() // height since we don't set a height in RenderView when we're printing. So without this quirk, the // height has nothing to be a percentage of, and it ends up being 0. That is bad. bool printingNeedsBaseHeight = document()->printing() && h.isPercent() - && (isRoot() || isBody() && document()->documentElement()->renderer()->style()->height().isPercent()); + && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->height().isPercent())); if (stretchesToViewHeight() || printingNeedsBaseHeight) { int margins = collapsedMarginTop() + collapsedMarginBottom(); int visHeight = document()->printing() ? view()->frameView()->visibleHeight() : view()->viewHeight(); @@ -2747,7 +2747,7 @@ VisiblePosition RenderBox::positionForPoint(const IntPoint& point) { // no children...return this render object's element, if there is one, and offset 0 if (!firstChild()) - return createVisiblePosition(firstDeepEditingPositionForNode(node())); + return createVisiblePosition(node() ? firstDeepEditingPositionForNode(node()) : Position(0, 0)); int xPos = point.x(); int yPos = point.y(); diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 23dad2d..98960e0 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -441,14 +441,14 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co if (baseColor.alpha() > 0) { context->save(); context->setCompositeOperation(CompositeCopy); - context->fillRect(rect, baseColor); + context->fillRect(rect, baseColor, style()->colorSpace()); context->restore(); } else context->clearRect(rect); } if (bgColor.isValid() && bgColor.alpha() > 0) - context->fillRect(rect, bgColor); + context->fillRect(rect, bgColor, style()->colorSpace()); } // no progressive loading of the background image @@ -477,7 +477,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co clientForBackgroundImage = bodyRenderer; } } - context->drawTiledImage(bg->image(clientForBackgroundImage, tileSize), destRect, phase, tileSize, compositeOp); + context->drawTiledImage(bg->image(clientForBackgroundImage, tileSize), style()->colorSpace(), destRect, phase, tileSize, compositeOp); } } @@ -706,6 +706,7 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, (imageHeight - topSlice - bottomSlice) > 0 && (h - topWidth - bottomWidth) > 0; Image* image = styleImage->image(this, imageSize); + ColorSpace colorSpace = style->colorSpace(); if (drawLeft) { // Paint the top and bottom left corners. @@ -713,18 +714,18 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, // The top left corner rect is (tx, ty, leftWidth, topWidth) // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice) if (drawTop) - graphicsContext->drawImage(image, IntRect(tx, ty, leftWidth, topWidth), + graphicsContext->drawImage(image, colorSpace, IntRect(tx, ty, leftWidth, topWidth), IntRect(0, 0, leftSlice, topSlice), op); // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth) // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice) if (drawBottom) - graphicsContext->drawImage(image, IntRect(tx, ty + h - bottomWidth, leftWidth, bottomWidth), + graphicsContext->drawImage(image, colorSpace, IntRect(tx, ty + h - bottomWidth, leftWidth, bottomWidth), IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op); // Paint the left edge. // Have to scale and tile into the border rect. - graphicsContext->drawTiledImage(image, IntRect(tx, ty + topWidth, leftWidth, + graphicsContext->drawTiledImage(image, colorSpace, IntRect(tx, ty + topWidth, leftWidth, h - topWidth - bottomWidth), IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice), Image::StretchTile, (Image::TileRule)vRule, op); @@ -735,17 +736,17 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth) // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice) if (drawTop) - graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty, rightWidth, topWidth), + graphicsContext->drawImage(image, colorSpace, IntRect(tx + w - rightWidth, ty, rightWidth, topWidth), IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op); // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth) // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice) if (drawBottom) - graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth), + graphicsContext->drawImage(image, colorSpace, IntRect(tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth), IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op); // Paint the right edge. - graphicsContext->drawTiledImage(image, IntRect(tx + w - rightWidth, ty + topWidth, rightWidth, + graphicsContext->drawTiledImage(image, colorSpace, IntRect(tx + w - rightWidth, ty + topWidth, rightWidth, h - topWidth - bottomWidth), IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice), Image::StretchTile, (Image::TileRule)vRule, op); @@ -753,20 +754,20 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, // Paint the top edge. if (drawTop) - graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty, w - leftWidth - rightWidth, topWidth), + graphicsContext->drawTiledImage(image, colorSpace, IntRect(tx + leftWidth, ty, w - leftWidth - rightWidth, topWidth), IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice), (Image::TileRule)hRule, Image::StretchTile, op); // Paint the bottom edge. if (drawBottom) - graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + h - bottomWidth, + graphicsContext->drawTiledImage(image, colorSpace, IntRect(tx + leftWidth, ty + h - bottomWidth, w - leftWidth - rightWidth, bottomWidth), IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice), (Image::TileRule)hRule, Image::StretchTile, op); // Paint the middle. if (drawMiddle) - graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + topWidth, w - leftWidth - rightWidth, + graphicsContext->drawTiledImage(image, colorSpace, IntRect(tx + leftWidth, ty + topWidth, w - leftWidth - rightWidth, h - topWidth - bottomWidth), IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice), (Image::TileRule)hRule, (Image::TileRule)vRule, op); @@ -1198,7 +1199,7 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int shadowOffset -= extraOffset; fillRect.move(extraOffset); - context->setShadow(shadowOffset, shadowBlur, shadowColor); + context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace()); if (hasBorderRadius) { IntRect rectToClipOut = rect; IntSize topLeftToClipOut = topLeft; @@ -1241,7 +1242,7 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int if (!rectToClipOut.isEmpty()) context->clipOutRoundedRect(rectToClipOut, topLeftToClipOut, topRightToClipOut, bottomLeftToClipOut, bottomRightToClipOut); - context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black); + context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black, s->colorSpace()); } else { IntRect rectToClipOut = rect; @@ -1258,7 +1259,7 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int if (!rectToClipOut.isEmpty()) context->clipOut(rectToClipOut); - context->fillRect(fillRect, Color::black); + context->fillRect(fillRect, Color::black, s->colorSpace()); } context->restore(); @@ -1269,9 +1270,9 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int if (holeRect.isEmpty()) { if (hasBorderRadius) - context->fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, shadowColor); + context->fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, shadowColor, s->colorSpace()); else - context->fillRect(rect, shadowColor); + context->fillRect(rect, shadowColor, s->colorSpace()); continue; } if (!begin) { @@ -1320,8 +1321,8 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int context->addPath(Path::createRectangle(holeRect)); context->setFillRule(RULE_EVENODD); - context->setFillColor(fillColor); - context->setShadow(shadowOffset, shadowBlur, shadowColor); + context->setFillColor(fillColor, s->colorSpace()); + context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace()); context->fillPath(); context->restore(); diff --git a/WebCore/rendering/RenderButton.cpp b/WebCore/rendering/RenderButton.cpp index f3ae558..3ecd382 100644 --- a/WebCore/rendering/RenderButton.cpp +++ b/WebCore/rendering/RenderButton.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the html renderer for KDE. - * * Copyright (C) 2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/RenderButton.h b/WebCore/rendering/RenderButton.h index 3a74589..7fd6ab0 100644 --- a/WebCore/rendering/RenderButton.h +++ b/WebCore/rendering/RenderButton.h @@ -1,6 +1,4 @@ /* - * This file is part of the html renderer for KDE. - * * Copyright (C) 2005 Apple Computer * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp index 17c6dad..b0aefc5 100644 --- a/WebCore/rendering/RenderCounter.cpp +++ b/WebCore/rendering/RenderCounter.cpp @@ -38,7 +38,7 @@ using namespace HTMLNames; typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap; typedef HashMap<const RenderObject*, CounterMap*> CounterMaps; -static CounterNode* counter(RenderObject*, const AtomicString& counterName, bool alwaysCreateCounter); +static CounterNode* makeCounterNode(RenderObject*, const AtomicString& counterName, bool alwaysCreateCounter); static CounterMaps& counterMaps() { @@ -53,30 +53,6 @@ static inline RenderObject* previousSiblingOrParent(RenderObject* object) return object->parent(); } -static CounterNode* lastDescendant(CounterNode* node) -{ - CounterNode* last = node->lastChild(); - if (!last) - return 0; - - while (CounterNode* lastChild = last->lastChild()) - last = lastChild; - - return last; -} - -static CounterNode* previousInPreOrder(CounterNode* node) -{ - CounterNode* previous = node->previousSibling(); - if (!previous) - return node->parent(); - - while (CounterNode* lastChild = previous->lastChild()) - previous = lastChild; - - return previous; -} - static bool planCounter(RenderObject* object, const AtomicString& counterName, bool& isReset, int& value) { ASSERT(object); @@ -133,59 +109,124 @@ static bool planCounter(RenderObject* object, const AtomicString& counterName, b return false; } -static bool findPlaceForCounter(RenderObject* object, const AtomicString& counterName, - bool isReset, CounterNode*& parent, CounterNode*& previousSibling) +// - Finds the insertion point for the counter described by counterOwner, isReset and +// identifier in the CounterNode tree for identifier and sets parent and +// previousSibling accordingly. +// - The function returns true if the counter whose insertion point is searched is NOT +// the root of the tree. +// - The root of the tree is a counter reference that is not in the scope of any other +// counter with the same identifier. +// - All the counter references with the same identifier as this one that are in +// children or subsequent siblings of the renderer that owns the root of the tree +// form the rest of of the nodes of the tree. +// - The root of the tree is always a reset type reference. +// - A subtree rooted at any reset node in the tree is equivalent to all counter +// references that are in the scope of the counter or nested counter defined by that +// reset node. +// - Non-reset CounterNodes cannot have descendants. + +static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& identifier, bool isReset, CounterNode*& parent, CounterNode*& previousSibling) { - // Find the appropriate previous sibling for insertion into the parent node - // by searching in render tree order for a child of the counter. - parent = 0; + // We cannot stop searching for counters with the same identifier before we also + // check this renderer, because it may affect the positioning in the tree of our counter. + RenderObject* searchEndRenderer = previousSiblingOrParent(counterOwner); + // We check renderers in preOrder from the renderer that our counter is attached to + // towards the begining of the document for counters with the same identifier as the one + // we are trying to find a place for. This is the next renderer to be checked. + RenderObject* currentRenderer = counterOwner->previousInPreOrder(); previousSibling = 0; - RenderObject* resetCandidate = isReset ? object->parent() : previousSiblingOrParent(object); - RenderObject* prevCounterCandidate = object; - CounterNode* candidateCounter = 0; - // When a reset counter is chosen as candidateCounter, we'll - // decide the new node should be a child of the reset node or a - // sibling or the reset node. This flag controls it. - bool createChildForReset = true; - while ((prevCounterCandidate = prevCounterCandidate->previousInPreOrder())) { - CounterNode* c = counter(prevCounterCandidate, counterName, false); - if (prevCounterCandidate == resetCandidate) { - if (!candidateCounter) { - candidateCounter = c; - createChildForReset = true; - } - if (candidateCounter) { - if (createChildForReset && candidateCounter->isReset()) { - parent = candidateCounter; - previousSibling = 0; - } else { - parent = candidateCounter->parent(); - previousSibling = candidateCounter; + while (currentRenderer) { + CounterNode* currentCounter = makeCounterNode(currentRenderer, identifier, false); + if (searchEndRenderer == currentRenderer) { + // We may be at the end of our search. + if (currentCounter) { + // We have a suitable counter on the EndSearchRenderer. + if (previousSibling) { // But we already found another counter that we come after. + if (currentCounter->isReset()) { + // We found a reset counter that is on a renderer that is a sibling of ours or a parent. + if (isReset && currentRenderer->parent() == counterOwner->parent()) { + // We are also a reset counter and the previous reset was on a sibling renderer + // hence we are the next sibling of that counter if that reset is not a root or + // we are a root node if that reset is a root. + parent = currentCounter->parent(); + previousSibling = parent ? currentCounter : 0; + return parent; + } + // We are not a reset node or the previous reset must be on an ancestor of our renderer + // hence we must be a child of that reset counter. + parent = currentCounter; + ASSERT(previousSibling->parent() == currentCounter); + return true; + } + // CurrentCounter, the counter at the EndSearchRenderer, is not reset. + if (!isReset || currentRenderer->parent() != counterOwner->parent()) { + // If the node we are placing is not reset or we have found a counter that is attached + // to an ancestor of the placed counter's renderer we know we are a sibling of that node. + ASSERT(currentCounter->parent() == previousSibling->parent()); + parent = currentCounter->parent(); + return true; + } + } else { + // We are at the potential end of the search, but we had no previous sibling candidate + // In this case we follow pretty much the same logic as above but no ASSERTs about + // previousSibling, and when we are a sibling of the end counter we must set previousSibling + // to currentCounter. + if (currentCounter->isReset()) { + if (isReset && currentRenderer->parent() == counterOwner->parent()) { + parent = currentCounter->parent(); + previousSibling = currentCounter; + return parent; + } + parent = currentCounter; + return true; + } + if (!isReset || currentRenderer->parent() != counterOwner->parent()) { + parent = currentCounter->parent(); + previousSibling = currentCounter; + return true; + } + previousSibling = currentCounter; } - return true; } - resetCandidate = previousSiblingOrParent(resetCandidate); - } else if (c) { - if (c->isReset()) { - if (c->parent()) { - // The new node may be the next sibling of this reset node. - createChildForReset = false; - candidateCounter = c; - } else { - createChildForReset = true; - candidateCounter = 0; - } - } else if (!candidateCounter) { - createChildForReset = true; - candidateCounter = c; + // We come here if the previous sibling or parent of our renderer had no + // good counter, or we are a reset node and the counter on the previous sibling + // of our renderer was not a reset counter. + // Set a new goal for the end of the search. + searchEndRenderer = previousSiblingOrParent(currentRenderer); + } else { + // We are searching descendants of a previous sibling of the renderer that the + // counter being placed is attached to. + if (currentCounter) { + // We found a suitable counter. + if (previousSibling) { + // Since we had a suitable previous counter before, we should only consider this one as our + // previousSibling if it is a reset counter and hence the current previousSibling is its child. + if (currentCounter->isReset()) { + previousSibling = currentCounter; + // We are no longer interested in previous siblings of the currentRenderer or their children + // as counters they may have attached cannot be the previous sibling of the counter we are placing. + currentRenderer = currentRenderer->parent(); + continue; + } + } else + previousSibling = currentCounter; + currentRenderer = previousSiblingOrParent(currentRenderer); + continue; } } + // This function is designed so that the same test is not done twice in an iteration, except for this one + // which may be done twice in some cases. Rearranging the decision points though, to accommodate this + // performance improvement would create more code duplication than is worthwhile in my oppinion and may further + // impede the readability of this already complex algorithm. + if (previousSibling) + currentRenderer = previousSiblingOrParent(currentRenderer); + else + currentRenderer = currentRenderer->previousInPreOrder(); } - return false; } -static CounterNode* counter(RenderObject* object, const AtomicString& counterName, bool alwaysCreateCounter) +static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& counterName, bool alwaysCreateCounter) { ASSERT(object); @@ -204,7 +245,7 @@ static CounterNode* counter(RenderObject* object, const AtomicString& counterNam CounterNode* newNode; if (findPlaceForCounter(object, counterName, isReset, newParent, newPreviousSibling)) { newNode = new CounterNode(object, isReset, value); - newParent->insertAfter(newNode, newPreviousSibling); + newParent->insertAfter(newNode, newPreviousSibling, counterName); } else { // Make a reset node for counters that aren't inside an existing reset node. newNode = new CounterNode(object, true, value); @@ -246,7 +287,7 @@ PassRefPtr<StringImpl> RenderCounter::originalText() const return 0; if (!m_counterNode) - m_counterNode = counter(parent(), m_counter.identifier(), true); + m_counterNode = makeCounterNode(parent(), m_counter.identifier(), true); CounterNode* child = m_counterNode; int value = child->isReset() ? child->value() : child->countInParent(); @@ -272,24 +313,26 @@ void RenderCounter::calcPrefWidths(int lead) RenderText::calcPrefWidths(lead); } -void RenderCounter::invalidate() +void RenderCounter::invalidate(const AtomicString& identifier) { + if (m_counter.identifier() != identifier) + return; m_counterNode = 0; setNeedsLayoutAndPrefWidthsRecalc(); } -static void destroyCounterNodeChildren(AtomicStringImpl* identifier, CounterNode* node) +static void destroyCounterNodeChildren(const AtomicString& identifier, CounterNode* node) { CounterNode* previous; - for (CounterNode* child = lastDescendant(node); child && child != node; child = previous) { - previous = previousInPreOrder(child); - child->parent()->removeChild(child); - ASSERT(counterMaps().get(child->renderer())->get(identifier) == child); - counterMaps().get(child->renderer())->remove(identifier); + for (CounterNode* child = node->lastDescendant(); child && child != node; child = previous) { + previous = child->previousInPreOrder(); + child->parent()->removeChild(child, identifier); + ASSERT(counterMaps().get(child->renderer())->get(identifier.impl()) == child); + counterMaps().get(child->renderer())->remove(identifier.impl()); if (!child->renderer()->documentBeingDestroyed()) { RenderObjectChildList* children = child->renderer()->virtualChildren(); if (children) - children->invalidateCounters(child->renderer()); + children->invalidateCounters(child->renderer(), identifier); } delete child; } @@ -306,9 +349,10 @@ void RenderCounter::destroyCounterNodes(RenderObject* object) CounterMap::const_iterator end = map->end(); for (CounterMap::const_iterator it = map->begin(); it != end; ++it) { CounterNode* node = it->second; - destroyCounterNodeChildren(it->first.get(), node); + AtomicString identifier(it->first.get()); + destroyCounterNodeChildren(identifier, node); if (CounterNode* parent = node->parent()) - parent->removeChild(node); + parent->removeChild(node, identifier); delete node; } diff --git a/WebCore/rendering/RenderCounter.h b/WebCore/rendering/RenderCounter.h index 961968e..356f1bd 100644 --- a/WebCore/rendering/RenderCounter.h +++ b/WebCore/rendering/RenderCounter.h @@ -33,7 +33,11 @@ class RenderCounter : public RenderText { public: RenderCounter(Document*, const CounterContent&); - void invalidate(); + // Removes the reference to the CounterNode associated with this renderer + // if its identifier matches the argument. + // This is used to cause a counter display update when the CounterNode + // tree for identifier changes. + void invalidate(const AtomicString& identifier); static void destroyCounterNodes(RenderObject*); diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index 8618d11..1f2b371 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 72623f7..37ee8fb 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -63,8 +63,13 @@ private: RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input) : RenderBlock(input) , m_button(0) - , m_fileChooser(FileChooser::create(this, input->value())) { + FileList* list = input->files(); + Vector<String> filenames; + unsigned length = list ? list->length() : 0; + for (unsigned i = 0; i < length; ++i) + filenames.append(list->item(i)->path()); + m_fileChooser = FileChooser::create(this, filenames); } RenderFileUploadControl::~RenderFileUploadControl() @@ -184,7 +189,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty) } if (paintInfo.phase == PaintPhaseForeground) { - const String& displayedFilename = m_fileChooser->basenameForWidth(style()->font(), maxFilenameWidth()); + const String& displayedFilename = fileTextValue(); unsigned length = displayedFilename.length(); const UChar* string = displayedFilename.characters(); TextRun textRun(string, length, false, 0, 0, style()->direction() == RTL, style()->unicodeBidi() == Override); @@ -204,7 +209,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty) + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop() + buttonRenderer->baselinePosition(true, false); - paintInfo.context->setFillColor(style()->color()); + paintInfo.context->setFillColor(style()->color(), style()->colorSpace()); // Draw the filename paintInfo.context->drawBidiText(style()->font(), textRun, IntPoint(textX, textY)); @@ -284,7 +289,7 @@ String RenderFileUploadControl::buttonValue() return m_button->value(); } -String RenderFileUploadControl::fileTextValue() +String RenderFileUploadControl::fileTextValue() const { return m_fileChooser->basenameForWidth(style()->font(), maxFilenameWidth()); } diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h index bd7d62a..72ba308 100644 --- a/WebCore/rendering/RenderFileUploadControl.h +++ b/WebCore/rendering/RenderFileUploadControl.h @@ -37,6 +37,8 @@ public: RenderFileUploadControl(HTMLInputElement*); virtual ~RenderFileUploadControl(); + virtual bool isFileUploadControl() const { return true; } + void click(); void valueChanged(); @@ -44,7 +46,7 @@ public: void receiveDroppedFiles(const Vector<String>&); String buttonValue(); - String fileTextValue(); + String fileTextValue() const; bool allowsMultipleFiles(); @@ -66,10 +68,16 @@ private: inline RenderFileUploadControl* toRenderFileUploadControl(RenderObject* object) { - ASSERT(!object || !strcmp(object->renderName(), "RenderFileUploadControl")); + ASSERT(!object || object->isFileUploadControl()); return static_cast<RenderFileUploadControl*>(object); } +inline const RenderFileUploadControl* toRenderFileUploadControl(const RenderObject* object) +{ + ASSERT(!object || object->isFileUploadControl()); + return static_cast<const RenderFileUploadControl*>(object); +} + // This will catch anyone doing an unnecessary cast. void toRenderFileUploadControl(const RenderFileUploadControl*); diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index f32e6e3..6882097 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -426,8 +426,13 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren) child->layer()->setStaticX(xPos); else child->layer()->setStaticX(width() - xPos); } - if (child->style()->hasStaticY()) - child->layer()->setStaticY(yPos); + if (child->style()->hasStaticY()) { + RenderLayer* childLayer = child->layer(); + if (childLayer->staticY() != yPos) { + child->layer()->setStaticY(yPos); + child->setChildNeedsLayout(true, false); + } + } child = iterator.next(); continue; } @@ -656,7 +661,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of // mainstream block layout); this is not really part of the XUL box model. - bool haveLineClamp = style()->lineClamp() >= 0 && style()->lineClamp() <= 100; + bool haveLineClamp = !style()->lineClamp().isNone(); if (haveLineClamp) { int maxLineCount = 0; child = iterator.first(); @@ -681,7 +686,8 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) // Get the # of lines and then alter all block flow children with auto height to use the // specified height. We always try to leave room for at least one line. - int numVisibleLines = max(1, static_cast<int>((maxLineCount + 1) * style()->lineClamp() / 100.0)); + LineClampValue lineClamp = style()->lineClamp(); + int numVisibleLines = lineClamp.isPercentage() ? max(1, (maxLineCount + 1) * lineClamp.value() / 100) : lineClamp.value(); if (numVisibleLines < maxLineCount) { for (child = iterator.first(); child; child = iterator.next()) { if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow()) @@ -712,28 +718,25 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) if (!lastLine) continue; - // See if the last item is an anchor - InlineBox* anchorBox = lastLine->lastChild(); - if (!anchorBox) - continue; - if (!anchorBox->renderer()->node()) - continue; - if (!anchorBox->renderer()->node()->isLink()) - continue; - RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1); if (!lastVisibleLine) continue; const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' }; DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2)); - + DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1)); const Font& font = style(numVisibleLines == 1)->font(); - int ellipsisAndSpaceWidth = font.width(TextRun(ellipsisAndSpace, 2)); - // Get ellipsis width + " " + anchor width - int totalWidth = ellipsisAndSpaceWidth + anchorBox->width(); - + // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too + int totalWidth; + InlineBox* anchorBox = lastLine->lastChild(); + if (anchorBox && anchorBox->renderer()->node() && anchorBox->renderer()->node()->isLink()) + totalWidth = anchorBox->width() + font.width(TextRun(ellipsisAndSpace, 2)); + else { + anchorBox = 0; + totalWidth = font.width(TextRun(&horizontalEllipsis, 1)); + } + // See if this width can be accommodated on the last visible line RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer()); RenderBlock* srcBlock = toRenderBlock(lastLine->renderer()); @@ -755,7 +758,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) continue; // Let the truncation code kick in. - lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, ltr, blockLeftEdge, blockRightEdge, totalWidth, anchorBox); + lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, ltr, blockLeftEdge, blockRightEdge, totalWidth, anchorBox); destBlock->setHasMarkupTruncation(true); } } @@ -785,8 +788,13 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren) else child->layer()->setStaticX(borderRight()+paddingRight()); } - if (child->style()->hasStaticY()) - child->layer()->setStaticY(height()); + if (child->style()->hasStaticY()) { + RenderLayer* childLayer = child->layer(); + if (childLayer->staticY() != height()) { + child->layer()->setStaticY(height()); + child->setChildNeedsLayout(true, false); + } + } child = iterator.next(); continue; } diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp index a855a08..09ad11f 100644 --- a/WebCore/rendering/RenderFrameSet.cpp +++ b/WebCore/rendering/RenderFrameSet.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the KDE project. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> * (C) 2000 Stefan Schimanski (1Stein@gmx.de) @@ -90,13 +88,14 @@ void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect // Fill first. GraphicsContext* context = paintInfo.context; - context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor()); + ColorSpace colorSpace = style()->colorSpace(); + context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor(), colorSpace); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. if (borderRect.width() >= 3) { - context->fillRect(IntRect(borderRect.topLeft(), IntSize(1, height())), borderStartEdgeColor()); - context->fillRect(IntRect(borderRect.topRight(), IntSize(1, height())), borderEndEdgeColor()); + context->fillRect(IntRect(borderRect.topLeft(), IntSize(1, height())), borderStartEdgeColor(), colorSpace); + context->fillRect(IntRect(borderRect.topRight(), IntSize(1, height())), borderEndEdgeColor(), colorSpace); } } @@ -109,13 +108,14 @@ void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& b // Fill first. GraphicsContext* context = paintInfo.context; - context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor()); + ColorSpace colorSpace = style()->colorSpace(); + context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor(), colorSpace); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. if (borderRect.height() >= 3) { - context->fillRect(IntRect(borderRect.topLeft(), IntSize(width(), 1)), borderStartEdgeColor()); - context->fillRect(IntRect(borderRect.bottomLeft(), IntSize(width(), 1)), borderEndEdgeColor()); + context->fillRect(IntRect(borderRect.topLeft(), IntSize(width(), 1)), borderStartEdgeColor(), colorSpace); + context->fillRect(IntRect(borderRect.bottomLeft(), IntSize(width(), 1)), borderEndEdgeColor(), colorSpace); } } diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index ff7c9c9..d06ca1f 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -53,7 +53,7 @@ namespace WebCore { static const double cInterpolationCutoff = 800. * 800.; static const double cLowQualityTimeThreshold = 0.050; // 50 ms -class RenderImageScaleData { +class RenderImageScaleData : public Noncopyable { public: RenderImageScaleData(RenderImage* image, const IntSize& size, double time, bool lowQualityScale) : m_size(size) @@ -371,8 +371,8 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) context->save(); #endif context->setStrokeStyle(SolidStroke); - context->setStrokeColor(Color::lightGray); - context->setFillColor(Color::transparent); + context->setStrokeColor(Color::lightGray, style()->colorSpace()); + context->setFillColor(Color::transparent, style()->colorSpace()); context->drawRect(IntRect(tx + leftBorder + leftPad, ty + topBorder + topPad, cWidth, cHeight)); #ifdef ANDROID_FIX // see http://b/issue?id=2052757 context->restore(); @@ -396,13 +396,13 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) centerY = 0; imageX = leftBorder + leftPad + centerX + 1; imageY = topBorder + topPad + centerY + 1; - context->drawImage(image(), IntPoint(tx + imageX, ty + imageY)); + context->drawImage(image(), style()->colorSpace(), IntPoint(tx + imageX, ty + imageY)); errorPictureDrawn = true; } if (!m_altText.isEmpty()) { String text = document()->displayStringModifiedByEncoding(m_altText); - context->setFillColor(style()->color()); + context->setFillColor(style()->color(), style()->colorSpace()); int ax = tx + leftBorder + leftPad; int ay = ty + topBorder + topPad; const Font& font = style()->font(); @@ -434,7 +434,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty) IntRect rect(IntPoint(tx + leftBorder + leftPad, ty + topBorder + topPad), contentSize); HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0; CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; - context->drawImage(image(cWidth, cHeight), rect, compositeOperator, useLowQualityScaling); + context->drawImage(image(cWidth, cHeight), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling); } } diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 8b0c3c7..6df5ffe 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -56,6 +56,7 @@ void RenderInline::destroy() // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise. children()->destroyLeftoverChildren(); +<<<<<<< HEAD:WebCore/rendering/RenderInline.cpp // Destroy our continuation before anything other than anonymous children. // The reason we don't destroy it before anonymous children is that they may // have continuations of their own that are anonymous children of our continuation. @@ -64,6 +65,16 @@ void RenderInline::destroy() m_continuation = 0; } +======= + // Destroy our continuation before anything other than anonymous children. + // The reason we don't destroy it before anonymous children is that they may + // have continuations of their own that are anonymous children of our continuation. + if (m_continuation) { + m_continuation->destroy(); + m_continuation = 0; + } + +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderInline.cpp if (!documentBeingDestroyed()) { if (firstLineBox()) { // We can't wait for RenderBoxModelObject::destroy to clear the selection, diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 8f2805a..ee7814c 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -243,14 +243,6 @@ bool RenderLayer::hasAcceleratedCompositing() const #endif } -void RenderLayer::setStaticY(int staticY) -{ - if (m_staticY == staticY) - return; - m_staticY = staticY; - renderer()->setChildNeedsLayout(true, false); -} - void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) { if (flags & DoFullRepaint) { @@ -383,6 +375,20 @@ TransformationMatrix RenderLayer::currentTransform() const return *m_transform; } +TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const +{ + if (!m_transform) + return TransformationMatrix(); + + if (paintBehavior & PaintBehaviorFlattenCompositingLayers) { + TransformationMatrix matrix = *m_transform; + makeMatrixRenderable(matrix, false /* flatten 3d */); + return matrix; + } + + return *m_transform; +} + void RenderLayer::setHasVisibleContent(bool b) { if (m_hasVisibleContent == b && !m_visibleContentStatusDirty) @@ -689,6 +695,27 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const } #endif +RenderLayer* RenderLayer::clippingRoot() const +{ + const RenderLayer* current = this; + while (current) { + if (current->renderer()->isRenderView()) + return const_cast<RenderLayer*>(current); + + current = compositingContainer(current); + ASSERT(current); + if (current->transform() +#if USE(ACCELERATED_COMPOSITING) + || current->isComposited() +#endif + ) + return const_cast<RenderLayer*>(current); + } + + ASSERT_NOT_REACHED(); + return 0; +} + IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const { // We don't use convertToLayerCoords because it doesn't know about transforms @@ -727,46 +754,18 @@ RenderLayer* RenderLayer::transparentPaintingAncestor() return 0; } -static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer) -{ - // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the - // paintDirtyRect, and that should cut down on the amount we have to paint. Still it - // would be better to respect clips. - - if (rootLayer != l && l->paintsWithTransform()) { - // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass - // the transformed layer and all of its children. - int x = 0; - int y = 0; - l->convertToLayerCoords(rootLayer, x, y); - - TransformationMatrix transform; - transform.translate(x, y); - transform = *l->transform() * transform; - transform = transform * enclosingTransform; +static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior); - // We now have a transform that will produce a rectangle in our view's space. - IntRect clipRect = transform.mapRect(l->boundingBox(l)); - - // Now shift the root layer to be us and pass down the new enclosing transform. - for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) { - if (!l->reflection() || l->reflectionLayer() != curr) - clipRect.unite(transparencyClipBox(transform, curr, l)); - } - - return clipRect; - } - - // Note: we don't have to walk z-order lists since transparent elements always establish - // a stacking context. This means we can just walk the layer tree directly. - IntRect clipRect = l->boundingBox(rootLayer); - +static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) +{ // If we have a mask, then the clip is limited to the border box area (and there is // no need to examine child layers). if (!l->renderer()->hasMask()) { + // Note: we don't have to walk z-order lists since transparent elements always establish + // a stacking context. This means we can just walk the layer tree directly. for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) { if (!l->reflection() || l->reflectionLayer() != curr) - clipRect.unite(transparencyClipBox(enclosingTransform, curr, rootLayer)); + clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior)); } } @@ -782,25 +781,54 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor clipRect.unite(l->renderBox()->reflectedRect(clipRect)); clipRect.move(deltaX, deltaY); } +} - // Now map the clipRect via the enclosing transform - return enclosingTransform.mapRect(clipRect); +static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) +{ + // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the + // paintDirtyRect, and that should cut down on the amount we have to paint. Still it + // would be better to respect clips. + + if (rootLayer != l && l->paintsWithTransform(paintBehavior)) { + // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass + // the transformed layer and all of its children. + int x = 0; + int y = 0; + l->convertToLayerCoords(rootLayer, x, y); + + TransformationMatrix transform; + transform.translate(x, y); + transform = *l->transform() * transform; + + IntRect clipRect = l->boundingBox(l); + expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior); + return transform.mapRect(clipRect); + } + + IntRect clipRect = l->boundingBox(rootLayer); + expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior); + return clipRect; } -void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer) +void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior) { - if (p->paintingDisabled() || (paintsWithTransparency() && m_usedTransparency)) + if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency)) return; RenderLayer* ancestor = transparentPaintingAncestor(); if (ancestor) - ancestor->beginTransparencyLayers(p, rootLayer); + ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior); - if (paintsWithTransparency()) { + if (paintsWithTransparency(paintBehavior)) { m_usedTransparency = true; p->save(); - p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer)); + IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior); + p->clip(clipRect); p->beginTransparencyLayer(renderer()->opacity()); +#ifdef REVEAL_TRANSPARENCY_LAYERS + p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f)); + p->fillRect(clipRect); +#endif } } @@ -1061,7 +1089,7 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) bool restrictedByLineClamp = false; if (renderer()->parent()) - restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; + restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { int newOffsetX = scrollXOffset() + xDelta; @@ -1205,7 +1233,7 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, bool restrictedByLineClamp = false; if (renderer()->parent()) { parentLayer = renderer()->parent()->enclosingLayer(); - restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; + restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); } if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { @@ -1921,7 +1949,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co return; } - context->fillRect(absRect, Color::white); + context->fillRect(absRect, Color::white, box->style()->colorSpace()); } void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) @@ -1950,7 +1978,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I // Paint the resizer control. DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner"))); IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height()); - context->drawImage(resizeCornerImage.get(), imagePoint); + context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint); // Draw a frame around the resizer (1px grey line) if there are any scrollbars present. // Clipping will exclude the right and bottom edges of this frame. @@ -1959,9 +1987,9 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I context->clip(absRect); IntRect largerCorner = absRect; largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1)); - context->setStrokeColor(Color(makeRGB(217, 217, 217))); + context->setStrokeColor(Color(makeRGB(217, 217, 217)), DeviceColorSpace); context->setStrokeThickness(1.0f); - context->setFillColor(Color::transparent); + context->setFillColor(Color::transparent, DeviceColorSpace); context->drawRect(largerCorner); context->restore(); } @@ -2044,10 +2072,10 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit return (didHorizontalScroll || didVerticalScroll); } -void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot) +void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) { RenderObject::OverlapTestRequestMap overlapTestRequests; - paintLayer(this, p, damageRect, paintRestriction, paintingRoot, &overlapTestRequests); + paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests); RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end(); for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) it->first->setOverlapTestResult(false); @@ -2091,7 +2119,7 @@ static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflect #endif void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, - const IntRect& paintDirtyRect, PaintRestriction paintRestriction, + const IntRect& paintDirtyRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests, PaintLayerFlags paintFlags) { @@ -2099,7 +2127,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (isComposited()) { // The updatingControlTints() painting pass goes through compositing layers, // but we need to ensure that we don't cache clip rects computed with the wrong root in this case. - if (p->updatingControlTints()) + if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers)) paintFlags |= PaintLayerTemporaryClipRects; else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) { // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer(). @@ -2118,19 +2146,20 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (!renderer()->opacity()) return; - if (paintsWithTransparency()) + if (paintsWithTransparency(paintBehavior)) paintFlags |= PaintLayerHaveTransparency; // Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate. - if (paintsWithTransform() && !(paintFlags & PaintLayerAppliedTransform)) { + if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) { + TransformationMatrix layerTransform = renderableTransform(paintBehavior); // If the transform can't be inverted, then don't paint anything. - if (!m_transform->isInvertible()) + if (!layerTransform.isInvertible()) return; // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency // layer from the parent now. if (paintFlags & PaintLayerHaveTransparency) - parent()->beginTransparencyLayers(p, rootLayer); + parent()->beginTransparencyLayers(p, rootLayer, paintBehavior); // Make sure the parent's clip rects have been calculated. IntRect clipRect = paintDirtyRect; @@ -2153,15 +2182,19 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, #else TransformationMatrix transform; transform.translate(x, y); +<<<<<<< HEAD:WebCore/rendering/RenderLayer.cpp transform = *m_transform * transform; #endif +======= + transform = layerTransform * transform; +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderLayer.cpp // Apply the transform. p->save(); p->concatCTM(transform); // Now do a paint with the root layer shifted to be us. - paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintRestriction, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); + paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); p->restore(); @@ -2178,7 +2211,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (m_reflection && !m_paintingInsideReflection) { // Mark that we are now inside replica painting. m_paintingInsideReflection = true; - reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); + reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); m_paintingInsideReflection = false; } @@ -2193,8 +2226,8 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Ensure our lists are up-to-date. updateCompositingAndLayerListsIfNeeded(); - bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; - bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; + bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; + bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). @@ -2212,7 +2245,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) { // Begin transparency layers lazily now that we know we have to paint something. if (haveTransparency) - beginTransparencyLayers(p, rootLayer); + beginTransparencyLayers(p, rootLayer, paintBehavior); // Paint our background first, before painting any child layers. // Establish the clip used to paint our background. @@ -2229,13 +2262,13 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Now walk the sorted list of children with negative z-indices. if (m_negZOrderList) for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); // Now establish the appropriate clip and paint our child RenderObjects. if (shouldPaint && !clipRectToApply.isEmpty()) { // Begin transparency layers lazily now that we know we have to paint something. if (haveTransparency) - beginTransparencyLayers(p, rootLayer); + beginTransparencyLayers(p, rootLayer, paintBehavior); // Set up the clip used when painting our children. setClip(p, paintDirtyRect, clipRectToApply); @@ -2268,12 +2301,12 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Paint any child layers that have overflow. if (m_normalFlowList) for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); // Now walk the sorted list of children with positive z-indices. if (m_posZOrderList) for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) { setClip(p, paintDirtyRect, damageRect); @@ -2813,17 +2846,49 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa IntRect RenderLayer::childrenClipRect() const { RenderLayer* rootLayer = renderer()->view()->layer(); + RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); - return foregroundRect; + calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox(); } IntRect RenderLayer::selfClipRect() const { RenderLayer* rootLayer = renderer()->view()->layer(); + RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); - return backgroundRect; + calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox(); +} + +void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds) +{ + m_blockSelectionGapsBounds.unite(bounds); +} + +void RenderLayer::clearBlockSelectionGapsBounds() +{ + m_blockSelectionGapsBounds = IntRect(); + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->clearBlockSelectionGapsBounds(); +} + +void RenderLayer::repaintBlockSelectionGaps() +{ + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->repaintBlockSelectionGaps(); + + if (m_blockSelectionGapsBounds.isEmpty()) + return; + + IntRect rect = m_blockSelectionGapsBounds; + rect.move(-scrolledContentOffset()); + if (renderer()->hasOverflowClip()) + rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0)); + if (renderer()->hasClip()) + rect.intersect(toRenderBox(renderer())->clipRect(0, 0)); + if (!rect.isEmpty()) + renderer()->repaintRectangle(rect); } bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index a274638..af64fc4 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -202,7 +202,7 @@ public: bool isTransparent() const; RenderLayer* transparentPaintingAncestor(); - void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer); + void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, PaintBehavior); bool hasReflection() const { return renderer()->hasReflection(); } RenderReplica* reflection() const { return m_reflection; } @@ -312,6 +312,10 @@ public: void clearClipRectsIncludingDescendants(); void clearClipRects(); + void addBlockSelectionGapsBounds(const IntRect&); + void clearBlockSelectionGapsBounds(); + void repaintBlockSelectionGaps(); + // Get the enclosing stacking context for this layer. A stacking context is a layer // that has a non-auto z-index. RenderLayer* stackingContext() const; @@ -336,6 +340,9 @@ public: // the <html> layer and the root layer). RenderLayer* enclosingPositionedAncestor() const; + // The layer relative to which clipping rects for this layer are computed. + RenderLayer* clippingRoot() const; + #if USE(ACCELERATED_COMPOSITING) // Enclosing compositing layer; if includeSelf is true, may return this. RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const; @@ -352,7 +359,7 @@ public: // paints the layers that intersect the damage rect from back to // front. The hitTest method looks for mouse events by walking // layers that intersect the point from front to back. - void paint(GraphicsContext*, const IntRect& damageRect, PaintRestriction = PaintRestrictionNone, RenderObject* paintingRoot = 0); + void paint(GraphicsContext*, const IntRect& damageRect, PaintBehavior = PaintBehaviorNormal, RenderObject* paintingRoot = 0); bool hitTest(const HitTestRequest&, HitTestResult&); // This method figures out our layerBounds in coordinates relative to @@ -390,7 +397,7 @@ public: int staticX() const { return m_staticX; } int staticY() const { return m_staticY; } void setStaticX(int staticX) { m_staticX = staticX; } - void setStaticY(int staticY); + void setStaticY(int staticY) { m_staticY = staticY; } bool hasTransform() const { return renderer()->hasTransform(); } // Note that this transform has the transform-origin baked in. @@ -399,6 +406,7 @@ public: // resulting transform has transform-origin baked in. If the layer does not have a transform, // returns the identity matrix. TransformationMatrix currentTransform() const; + TransformationMatrix renderableTransform(PaintBehavior) const; // Get the perspective transform, which is applied to transformed sublayers. // Returns true if the layer has a -webkit-perspective. @@ -426,14 +434,14 @@ public: bool hasCompositedMask() const { return false; } #endif - bool paintsWithTransparency() const + bool paintsWithTransparency(PaintBehavior paintBehavior) const { - return isTransparent() && !isComposited(); + return isTransparent() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || !isComposited()); } - bool paintsWithTransform() const + bool paintsWithTransform(PaintBehavior paintBehavior) const { - return transform() && !isComposited(); + return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || !isComposited()); } private: @@ -465,7 +473,7 @@ private: typedef unsigned PaintLayerFlags; void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, - PaintRestriction, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0, + PaintBehavior, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0, PaintLayerFlags paintFlags = 0); RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, @@ -644,6 +652,9 @@ protected: RenderScrollbarPart* m_scrollCorner; RenderScrollbarPart* m_resizer; +private: + IntRect m_blockSelectionGapsBounds; + #if USE(ACCELERATED_COMPOSITING) OwnPtr<RenderLayerBacking> m_backing; #endif diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index d7248d4..a62c1be 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -28,7 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) #include "AnimationController.h" -#include "CanvasRenderingContext3D.h" +#if ENABLE(3D_CANVAS) +#include "WebGLRenderingContext.h" +#endif #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" #include "FrameView.h" @@ -37,11 +39,14 @@ #include "HTMLCanvasElement.h" #include "HTMLElement.h" #include "HTMLNames.h" +#include "InspectorTimelineAgent.h" +#include "KeyframeList.h" #include "RenderBox.h" #include "RenderImage.h" #include "RenderLayerCompositor.h" #include "RenderVideo.h" #include "RenderView.h" +#include "Settings.h" #include "RenderLayerBacking.h" @@ -192,7 +197,7 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() else if (renderer()->isCanvas()) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); if (canvas->is3D()) { - CanvasRenderingContext3D* context = static_cast<CanvasRenderingContext3D*>(canvas->renderingContext()); + WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(canvas->renderingContext()); if (context->graphicsContext3D()->platformGraphicsContext3D()) m_graphicsLayer->setContentsToGraphicsContext3D(context->graphicsContext3D()); } @@ -849,7 +854,7 @@ static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase? void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context, const IntRect& paintDirtyRect, // in the coords of rootLayer - PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase, + PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase, RenderObject* paintingRoot) { if (paintingGoesToWindow()) { @@ -863,7 +868,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* if (m_owningLayer->hasReflection()) { // Mark that we are now inside replica painting. m_owningLayer->setPaintingInsideReflection(true); - m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection); + m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection); m_owningLayer->setPaintingInsideReflection(false); } @@ -899,9 +904,9 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* int rw; int rh; - if (box->view()->frameView()) { - rw = box->view()->frameView()->contentsWidth(); - rh = box->view()->frameView()->contentsHeight(); + if (FrameView* frameView = box->view()->frameView()) { + rw = frameView->contentsWidth(); + rh = frameView->contentsHeight(); } else { rw = box->view()->width(); rh = box->view()->height(); @@ -930,8 +935,8 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* restoreClip(context, paintDirtyRect, damageRect); } - bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; - bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; + bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; + bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. @@ -939,7 +944,7 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList(); if (negZOrderList) { for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot); + it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); } // Set up the clip used when painting our children. @@ -975,14 +980,14 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList(); if (normalFlowList) { for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) - it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot); + it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); } // Now walk the sorted list of children with positive z-indices. Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList(); if (posZOrderList) { for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot); + it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); } } @@ -1002,9 +1007,25 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* ASSERT(!m_owningLayer->m_usedTransparency); } +static InspectorTimelineAgent* inspectorTimelineAgent(RenderObject* renderer) +{ + Frame* frame = renderer->document()->frame(); + if (!frame) + return 0; + Page* page = frame->page(); + if (!page) + return 0; + return page->inspectorTimelineAgent(); +} + // Up-call from compositing layer drawing callback. void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) { +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(m_owningLayer->renderer())) + timelineAgent->willPaint(clip); +#endif + // We have to use the same root as for hit testing, because both methods // can compute and cache clipRects. IntRect enclosingBBox = compositedBounds(); @@ -1021,7 +1042,22 @@ void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& co IntRect dirtyRect = enclosingBBox; dirtyRect.intersect(clipRect); - paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, paintingPhase, renderer()); + paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer()); + +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(m_owningLayer->renderer())) + timelineAgent->didPaint(); +#endif +} + +bool RenderLayerBacking::showDebugBorders() const +{ + return compositor() ? compositor()->showDebugBorders() : false; +} + +bool RenderLayerBacking::showRepaintCounter() const +{ + return compositor() ? compositor()->showRepaintCounter() : false; } bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes) diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index 17bcaf7..2bbb37f 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -119,6 +119,9 @@ public: virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip); + virtual bool showDebugBorders() const; + virtual bool showRepaintCounter() const; + IntRect contentsBox() const; private: @@ -160,7 +163,7 @@ private: bool hasNonCompositingContent() const; void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, - PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); + PaintBehavior paintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot); static int graphicsLayerToCSSProperty(AnimatedPropertyID); static AnimatedPropertyID cssToGraphicsLayerProperty(int); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index 5201287..2f5e267 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -79,6 +79,8 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) : m_renderView(renderView) , m_rootPlatformLayer(0) , m_hasAcceleratedCompositing(true) + , m_showDebugBorders(false) + , m_showRepaintCounter(false) , m_compositingConsultsOverlap(true) , m_compositing(false) , m_rootLayerAttached(false) @@ -109,16 +111,24 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) } } -void RenderLayerCompositor::cacheAcceleratedCompositingEnabledFlag() +void RenderLayerCompositor::cacheAcceleratedCompositingFlags() { bool hasAcceleratedCompositing = false; - if (Settings* settings = m_renderView->document()->settings()) + bool showDebugBorders = false; + bool showRepaintCounter = false; + + if (Settings* settings = m_renderView->document()->settings()) { hasAcceleratedCompositing = settings->acceleratedCompositingEnabled(); + showDebugBorders = settings->showDebugBorders(); + showRepaintCounter = settings->showRepaintCounter(); + } - if (hasAcceleratedCompositing != m_hasAcceleratedCompositing) + if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter) setCompositingLayersNeedRebuild(); m_hasAcceleratedCompositing = hasAcceleratedCompositing; + m_showDebugBorders = showDebugBorders; + m_showRepaintCounter = showRepaintCounter; } void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild) @@ -175,10 +185,18 @@ void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) needLayerRebuild |= layersChanged; } - // Now create and parent the compositing layers. - { + if (needLayerRebuild) { + // Now updated and parent the compositing layers. CompositingState compState(updateRoot); - rebuildCompositingLayerTree(updateRoot, compState, needLayerRebuild); + Vector<GraphicsLayer*> childList; + rebuildCompositingLayerTree(updateRoot, compState, childList); + + // Host the document layer in the RenderView's root layer. + if (updateRoot == rootRenderLayer() && !childList.isEmpty()) + m_rootPlatformLayer->setChildren(childList); + } else { + // We just need to do a geometry update. + updateLayerTreeGeometry(updateRoot); } #if PROFILE_LAYER_REBUILD @@ -328,7 +346,7 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye } } - if (layer->paintsWithTransform()) { + if (layer->paintsWithTransform(PaintBehaviorNormal)) { TransformationMatrix* affineTrans = layer->transform(); boundingBoxRect = affineTrans->mapRect(boundingBoxRect); unionBounds = affineTrans->mapRect(unionBounds); @@ -476,7 +494,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O // If we have to make a layer for this child, make one now so we can have a contents layer // (since we need to ensure that the -ve z-order child renders underneath our contents). - if (childState.m_subtreeIsCompositing) { + if (!willBeComposited && childState.m_subtreeIsCompositing) { // make layer compositing layer->setMustOverlapCompositedLayers(true); childState.m_compositingAncestor = layer; @@ -509,7 +527,7 @@ 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 (childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { + if (!willBeComposited && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { layer->setMustOverlapCompositedLayers(true); if (overlapMap) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); @@ -586,11 +604,12 @@ bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const } #endif -void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& compositingState, bool updateHierarchy) +void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, const CompositingState& compositingState, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer) { // Make the layer compositing if necessary, and set up clipping and content layers. // Note that we can only do work here that is independent of whether the descendant layers // have been processed. computeCompositingRequirements() will already have done the repaint if necessary. + RenderLayerBacking* layerBacking = layer->backing(); if (layerBacking) { // The compositing state of all our children has been updated already, so now @@ -601,15 +620,12 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru if (!layer->parent()) updateRootLayerPosition(); - - // FIXME: make this more incremental - if (updateHierarchy) - layerBacking->parentForSublayers()->removeAllChildren(); } - // host the document layer in the RenderView's root layer - if (updateHierarchy && layer->isRootLayer() && layer->isComposited()) - parentInRootLayer(layer); + // If this layer has backing, then we are collecting its children, otherwise appending + // to the compositing child list of an enclosing layer. + Vector<GraphicsLayer*> layerChildren; + Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer; CompositingState childState = compositingState; if (layer->isComposited()) @@ -630,19 +646,13 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru size_t listSize = negZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); - rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); - if (updateHierarchy && curLayer->isComposited()) - setCompositingParent(curLayer, childState.m_compositingAncestor); + rebuildCompositingLayerTree(curLayer, childState, childList); } } - if (updateHierarchy && layerBacking && layerBacking->foregroundLayer()) { - layerBacking->foregroundLayer()->removeFromParent(); - - // The foreground layer has to be correctly sorted with child layers, so needs to become a child of the clipping layer. - GraphicsLayer* hostingLayer = layerBacking->parentForSublayers(); - hostingLayer->addChild(layerBacking->foregroundLayer()); - } + // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. + if (layerBacking && layerBacking->foregroundLayer()) + childList.append(layerBacking->foregroundLayer()); } ASSERT(!layer->m_normalFlowListDirty); @@ -650,9 +660,7 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru size_t listSize = normalFlowList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); - rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); - if (updateHierarchy && curLayer->isComposited()) - setCompositingParent(curLayer, childState.m_compositingAncestor); + rebuildCompositingLayerTree(curLayer, childState, childList); } } @@ -661,14 +669,60 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru size_t listSize = posZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); - rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); - if (updateHierarchy && curLayer->isComposited()) - setCompositingParent(curLayer, childState.m_compositingAncestor); + rebuildCompositingLayerTree(curLayer, childState, childList); } } } + + if (layerBacking) { + layerBacking->parentForSublayers()->setChildren(layerChildren); + childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers()); + } } +// This just updates layer geometry without changing the hierarchy. +void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer) +{ + if (RenderLayerBacking* layerBacking = layer->backing()) { + // The compositing state of all our children has been updated already, so now + // we can compute and cache the composited bounds for this layer. + layerBacking->updateCompositedBounds(); + + if (layer->reflectionLayer()) + layer->reflectionLayer()->backing()->updateCompositedBounds(); + + layerBacking->updateGraphicsLayerConfiguration(); + layerBacking->updateGraphicsLayerGeometry(); + + if (!layer->parent()) + updateRootLayerPosition(); + } + + if (layer->isStackingContext()) { + ASSERT(!layer->m_zOrderListsDirty); + + if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) + updateLayerTreeGeometry(negZOrderList->at(i)); + } + } + + ASSERT(!layer->m_normalFlowListDirty); + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) + updateLayerTreeGeometry(normalFlowList->at(i)); + } + + if (layer->isStackingContext()) { + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) + updateLayerTreeGeometry(posZOrderList->at(i)); + } + } +} // Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry. void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth updateDepth) @@ -716,6 +770,7 @@ void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& a void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect) { + // FIXME: This method does not work correctly with transforms. if (layer->isComposited()) layer->setBackingNeedsRepaintInRect(rect); @@ -724,7 +779,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = negZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); - int x = 0, y = 0; + int x = 0; + int y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); @@ -736,7 +792,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = posZOrderList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); - int x = 0, y = 0; + int x = 0; + int y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); @@ -748,7 +805,8 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const size_t listSize = normalFlowList->size(); for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); - int x = 0, y = 0; + int x = 0; + int y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index a809a70..73683f3 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -61,8 +61,11 @@ public: // Returns true if the accelerated compositing is enabled bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; } - // Copy the acceleratedCompositingEnabledFlag from Settings - void cacheAcceleratedCompositingEnabledFlag(); + bool showDebugBorders() const { return m_showDebugBorders; } + bool showRepaintCounter() const { return m_showRepaintCounter; } + + // Copy the accelerated compositing related flags from Settings + void cacheAcceleratedCompositingFlags(); // Called when the layer hierarchy needs to be updated (compositing layers have been // created, destroyed or re-parented). @@ -147,8 +150,13 @@ private: // Returns true if any layer's compositing changed void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged); - void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState&, bool updateHierarchy); + + // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer. + void rebuildCompositingLayerTree(RenderLayer* layer, const struct CompositingState&, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer); + // Recurses down the tree, updating layer geometry only. + void updateLayerTreeGeometry(RenderLayer*); + // Hook compositing layers together void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer); void removeCompositedChildren(RenderLayer*); @@ -171,6 +179,8 @@ private: RenderView* m_renderView; OwnPtr<GraphicsLayer> m_rootPlatformLayer; bool m_hasAcceleratedCompositing; + bool m_showDebugBorders; + bool m_showRepaintCounter; bool m_compositingConsultsOverlap; bool m_compositing; bool m_rootLayerAttached; diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 76a2e2f..57bc26c 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -199,6 +199,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::Pain int bottom = curr->bottomVisibleOverflow() + renderer->maximalOutlineSize(info.phase); h = bottom - top; yPos = ty + top; + v->setMinimumColumnHeight(h); if (yPos < info.rect.bottom() && yPos + h > info.rect.y()) curr->paint(info, tx, ty); } diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 0edfdef..15c652c 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -321,7 +321,8 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in textColor = theme()->inactiveListBoxSelectionForegroundColor(); } - paintInfo.context->setFillColor(textColor); + ColorSpace colorSpace = itemStyle->colorSpace(); + paintInfo.context->setFillColor(textColor, colorSpace); Font itemFont = style()->font(); if (isOptionGroupElement(element)) { @@ -358,9 +359,10 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, in // Draw the background for this list box item if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) { + ColorSpace colorSpace = element->renderStyle() ? element->renderStyle()->colorSpace() : style()->colorSpace(); IntRect itemRect = itemBoundingBoxRect(tx, ty, listIndex); itemRect.intersect(controlClipRect(tx, ty)); - paintInfo.context->fillRect(itemRect, backColor); + paintInfo.context->fillRect(itemRect, backColor, colorSpace); } } diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index e487c60..539b8c7 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index 9627711..eab4404 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -48,7 +48,9 @@ static String toRoman(int number, bool upper) if (number < 1 || number > 3999) return String::number(number); - const int lettersSize = 12; // big enough for three each of I, X, C, and M + // Big enough to store largest roman number less than 3999 which + // is 3888 (MMMDCCCLXXXVIII) + const int lettersSize = 15; UChar letters[lettersSize]; int length = 0; @@ -543,10 +545,10 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled()) paintCustomHighlight(tx, ty, style()->highlight(), true); #endif - context->drawImage(m_image->image(this, marker.size()), marker.location()); + context->drawImage(m_image->image(this, marker.size()), style()->colorSpace(), marker.location()); if (selectionState() != SelectionNone) { // FIXME: selectionRect() is in absolute, not painting coordinates. - context->fillRect(selectionRect(), selectionBackgroundColor()); + context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace()); } return; } @@ -559,21 +561,21 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) if (selectionState() != SelectionNone) { // FIXME: selectionRect() is in absolute, not painting coordinates. - context->fillRect(selectionRect(), selectionBackgroundColor()); + context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace()); } const Color color(style()->color()); - context->setStrokeColor(color); + context->setStrokeColor(color, style()->colorSpace()); context->setStrokeStyle(SolidStroke); context->setStrokeThickness(1.0f); - context->setFillColor(color); + context->setFillColor(color, style()->colorSpace()); switch (style()->listStyleType()) { case DISC: context->drawEllipse(marker); return; case CIRCLE: - context->setFillColor(Color::transparent); + context->setFillColor(Color::transparent, DeviceColorSpace); context->drawEllipse(marker); return; case SQUARE: diff --git a/WebCore/rendering/RenderMarquee.h b/WebCore/rendering/RenderMarquee.h index 886c343..1651454 100644 --- a/WebCore/rendering/RenderMarquee.h +++ b/WebCore/rendering/RenderMarquee.h @@ -53,7 +53,7 @@ namespace WebCore { class RenderLayer; // This class handles the auto-scrolling of layers with overflow: marquee. -class RenderMarquee { +class RenderMarquee : public Noncopyable { public: RenderMarquee(RenderLayer*); diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp index 1d4da23..2ff50df 100644 --- a/WebCore/rendering/RenderMedia.cpp +++ b/WebCore/rendering/RenderMedia.cpp @@ -121,6 +121,8 @@ void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldSty m_rewindButton->updateStyle(); if (m_returnToRealtimeButton) m_returnToRealtimeButton->updateStyle(); + if (m_toggleClosedCaptionsButton) + m_toggleClosedCaptionsButton->updateStyle(); if (m_statusDisplay) m_statusDisplay->updateStyle(); if (m_timelineContainer) @@ -223,6 +225,13 @@ void RenderMedia::createReturnToRealtimeButton() m_returnToRealtimeButton->attachToParent(m_panel.get()); } +void RenderMedia::createToggleClosedCaptionsButton() +{ + ASSERT(!m_toggleClosedCaptionsButton); + m_toggleClosedCaptionsButton = new MediaControlToggleClosedCaptionsButtonElement(document(), mediaElement()); + m_toggleClosedCaptionsButton->attachToParent(m_panel.get()); +} + void RenderMedia::createStatusDisplay() { ASSERT(!m_statusDisplay); @@ -310,6 +319,7 @@ void RenderMedia::updateControls() m_volumeSliderContainer = 0; m_volumeSlider = 0; m_controlsShadowRoot = 0; + m_toggleClosedCaptionsButton = 0; } m_opacityAnimationTo = 1.0f; m_opacityAnimationTimer.stop(); @@ -333,6 +343,7 @@ void RenderMedia::updateControls() } createSeekBackButton(); createSeekForwardButton(); + createToggleClosedCaptionsButton(); createFullscreenButton(); createMuteButton(); createVolumeSliderContainer(); @@ -379,6 +390,8 @@ void RenderMedia::updateControls() m_rewindButton->update(); if (m_returnToRealtimeButton) m_returnToRealtimeButton->update(); + if (m_toggleClosedCaptionsButton) + m_toggleClosedCaptionsButton->update(); if (m_statusDisplay) m_statusDisplay->update(); if (m_fullscreenButton) @@ -535,6 +548,9 @@ void RenderMedia::forwardEvent(Event* event) if (m_returnToRealtimeButton && m_returnToRealtimeButton->hitTest(point)) m_returnToRealtimeButton->defaultEventHandler(event); + if (m_toggleClosedCaptionsButton && m_toggleClosedCaptionsButton->hitTest(point)) + m_toggleClosedCaptionsButton->defaultEventHandler(event); + if (m_timeline && m_timeline->hitTest(point)) m_timeline->defaultEventHandler(event); diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h index 602cd26..066b83d 100644 --- a/WebCore/rendering/RenderMedia.h +++ b/WebCore/rendering/RenderMedia.h @@ -40,6 +40,7 @@ class MediaControlPlayButtonElement; class MediaControlSeekButtonElement; class MediaControlRewindButtonElement; class MediaControlReturnToRealtimeButtonElement; +class MediaControlToggleClosedCaptionsButtonElement; class MediaControlTimelineElement; class MediaControlVolumeSliderElement; class MediaControlFullscreenButtonElement; @@ -96,6 +97,7 @@ private: void createSeekForwardButton(); void createRewindButton(); void createReturnToRealtimeButton(); + void createToggleClosedCaptionsButton(); void createStatusDisplay(); void createTimelineContainer(); void createTimeline(); @@ -123,6 +125,7 @@ private: RefPtr<MediaControlSeekButtonElement> m_seekForwardButton; RefPtr<MediaControlRewindButtonElement> m_rewindButton; RefPtr<MediaControlReturnToRealtimeButtonElement> m_returnToRealtimeButton; + RefPtr<MediaControlToggleClosedCaptionsButtonElement> m_toggleClosedCaptionsButton; RefPtr<MediaControlTimelineElement> m_timeline; RefPtr<MediaControlVolumeSliderElement> m_volumeSlider; RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton; diff --git a/WebCore/rendering/RenderMediaControls.cpp b/WebCore/rendering/RenderMediaControls.cpp index 9cc1493..17576ae 100644 --- a/WebCore/rendering/RenderMediaControls.cpp +++ b/WebCore/rendering/RenderMediaControls.cpp @@ -90,6 +90,15 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R case MediaFullscreenButton: paintThemePart(SafariTheme::MediaFullscreenButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); break; + case MediaShowClosedCaptionsButton: + case MediaHideClosedCaptionsButton: +#if SAFARI_THEME_VERSION >= 4 + if (MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(o->node())) { + bool captionsVisible = btn->displayType() == MediaHideClosedCaptionsButton; + paintThemePart(captionsVisible ? SafariTheme::MediaHideClosedCaptionsButtonPart : SafariTheme::MediaShowClosedCaptionsButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o)); + } +#endif + break; case MediaMuteButton: case MediaUnMuteButton: if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) { diff --git a/WebCore/rendering/RenderMediaControlsChromium.cpp b/WebCore/rendering/RenderMediaControlsChromium.cpp index 56fbec4..50feb46 100644 --- a/WebCore/rendering/RenderMediaControlsChromium.cpp +++ b/WebCore/rendering/RenderMediaControlsChromium.cpp @@ -63,7 +63,7 @@ static bool hasSource(const HTMLMediaElement* mediaElement) static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image) { IntRect imageRect = image->rect(); - context->drawImage(image, rect); + context->drawImage(image, DeviceColorSpace, rect); return true; } @@ -114,9 +114,9 @@ static bool paintMediaSlider(RenderObject* object, const RenderObject::PaintInfo context->save(); context->setShouldAntialias(true); context->setStrokeStyle(SolidStroke); - context->setStrokeColor(style->borderLeftColor()); + context->setStrokeColor(style->borderLeftColor(), DeviceColorSpace); context->setStrokeThickness(style->borderLeftWidth()); - context->setFillColor(style->backgroundColor()); + context->setFillColor(style->backgroundColor(), DeviceColorSpace); context->drawRect(rect); context->restore(); @@ -172,13 +172,13 @@ static bool paintMediaVolumeSlider(RenderObject* object, const RenderObject::Pai GraphicsContext* context = paintInfo.context; Color originalColor = context->strokeColor(); if (originalColor != Color::white) - context->setStrokeColor(Color::white); + context->setStrokeColor(Color::white, DeviceColorSpace); int x = rect.x() + rect.width() / 2; context->drawLine(IntPoint(x, rect.y()), IntPoint(x, rect.y() + rect.height())); if (originalColor != Color::white) - context->setStrokeColor(originalColor); + context->setStrokeColor(originalColor, DeviceColorSpace); return true; } @@ -207,17 +207,17 @@ static bool paintMediaTimelineContainer(RenderObject* object, const RenderObject // Draw the left border using CSS defined width and color. context->setStrokeThickness(object->style()->borderLeftWidth()); - context->setStrokeColor(object->style()->borderLeftColor().rgb()); + context->setStrokeColor(object->style()->borderLeftColor().rgb(), DeviceColorSpace); context->drawLine(IntPoint(rect.x() + 1, rect.y()), IntPoint(rect.x() + 1, rect.y() + rect.height())); // Draw the right border using CSS defined width and color. context->setStrokeThickness(object->style()->borderRightWidth()); - context->setStrokeColor(object->style()->borderRightColor().rgb()); + context->setStrokeColor(object->style()->borderRightColor().rgb(), DeviceColorSpace); context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()), IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height())); - context->setStrokeColor(originalColor); + context->setStrokeColor(originalColor, DeviceColorSpace); context->setStrokeThickness(originalThickness); context->setStrokeStyle(originalStyle); } @@ -275,6 +275,8 @@ bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType case MediaRewindButton: case MediaReturnToRealtimeButton: case MediaStatusDisplay: + case MediaShowClosedCaptionsButton: + case MediaHideClosedCaptionsButton: ASSERT_NOT_REACHED(); break; } diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 21ced26..712519b 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -4,6 +4,7 @@ * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -41,6 +42,8 @@ #include "RenderImageGeneratedContent.h" #include "RenderInline.h" #include "RenderListItem.h" +#include "RenderRuby.h" +#include "RenderRubyText.h" #include "RenderTableCell.h" #include "RenderTableCol.h" #include "RenderTableRow.h" @@ -106,46 +109,42 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) return image; } - RenderObject* o = 0; + if (node->hasTagName(rubyTag)) { + if (style->display() == INLINE) + return new (arena) RenderRubyAsInline(node); + else + 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); switch (style->display()) { case NONE: - break; + return 0; case INLINE: - o = new (arena) RenderInline(node); - break; + return new (arena) RenderInline(node); case BLOCK: - o = new (arena) RenderBlock(node); - break; case INLINE_BLOCK: - o = new (arena) RenderBlock(node); - break; - case LIST_ITEM: - o = new (arena) RenderListItem(node); - break; case RUN_IN: case COMPACT: - o = new (arena) RenderBlock(node); - break; + return new (arena) RenderBlock(node); + case LIST_ITEM: + return new (arena) RenderListItem(node); case TABLE: case INLINE_TABLE: - o = new (arena) RenderTable(node); - break; + return new (arena) RenderTable(node); case TABLE_ROW_GROUP: case TABLE_HEADER_GROUP: case TABLE_FOOTER_GROUP: - o = new (arena) RenderTableSection(node); - break; + return new (arena) RenderTableSection(node); case TABLE_ROW: - o = new (arena) RenderTableRow(node); - break; + return new (arena) RenderTableRow(node); case TABLE_COLUMN_GROUP: case TABLE_COLUMN: - o = new (arena) RenderTableCol(node); - break; + return new (arena) RenderTableCol(node); case TABLE_CELL: - o = new (arena) RenderTableCell(node); - break; + return new (arena) RenderTableCell(node); case TABLE_CAPTION: #if ENABLE(WCSS) // As per the section 17.1 of the spec WAP-239-WCSS-20011026-a.pdf, @@ -153,15 +152,13 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) // principal block box ([CSS2] section 9.2.1). case WAP_MARQUEE: #endif - o = new (arena) RenderBlock(node); - break; + return new (arena) RenderBlock(node); case BOX: case INLINE_BOX: - o = new (arena) RenderFlexibleBox(node); - break; + return new (arena) RenderFlexibleBox(node); } - return o; + return 0; } #ifndef NDEBUG @@ -646,7 +643,7 @@ RenderBlock* RenderObject::containingBlock() const } if (!o || !o->isRenderBlock()) - return 0; // Probably doesn't happen any more, but leave just in case. -dwh + return 0; // This can still happen in case of an orphaned tree return toRenderBlock(o); } @@ -722,7 +719,7 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, return; case DOTTED: case DASHED: - graphicsContext->setStrokeColor(c); + graphicsContext->setStrokeColor(c, m_style->colorSpace()); graphicsContext->setStrokeThickness(width); graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke); @@ -743,7 +740,7 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, if (adjbw1 == 0 && adjbw2 == 0) { graphicsContext->setStrokeStyle(NoStroke); - graphicsContext->setFillColor(c); + graphicsContext->setFillColor(c, m_style->colorSpace()); switch (s) { case BSTop: case BSBottom: @@ -856,7 +853,7 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, // fall through case SOLID: { graphicsContext->setStrokeStyle(NoStroke); - graphicsContext->setFillColor(c); + graphicsContext->setFillColor(c, m_style->colorSpace()); ASSERT(x2 >= x1); ASSERT(y2 >= y1); if (!adjbw1 && !adjbw2) { @@ -916,7 +913,7 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in return; case DOTTED: case DASHED: - graphicsContext->setStrokeColor(c); + graphicsContext->setStrokeColor(c, m_style->colorSpace()); graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke); graphicsContext->setStrokeThickness(thickness); graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); @@ -938,7 +935,7 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in } graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(c); + graphicsContext->setStrokeColor(c, m_style->colorSpace()); graphicsContext->setStrokeThickness(third); graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan); graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird); @@ -957,13 +954,13 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in } graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(c); + graphicsContext->setStrokeColor(c, m_style->colorSpace()); graphicsContext->setStrokeThickness(thickness); graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); float halfThickness = (thickness + 1.0f) / 4.0f; int shiftForInner = static_cast<int>(halfThickness * 1.5f); - graphicsContext->setStrokeColor(c2); + graphicsContext->setStrokeColor(c2, m_style->colorSpace()); graphicsContext->setStrokeThickness(halfThickness > 2 ? halfThickness - 1 : halfThickness); graphicsContext->strokeArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2, (radius.height() - shiftForInner) * 2), angleStart, angleSpan); @@ -977,7 +974,7 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in c = c.dark(); case SOLID: graphicsContext->setStrokeStyle(SolidStroke); - graphicsContext->setStrokeColor(c); + graphicsContext->setStrokeColor(c, m_style->colorSpace()); graphicsContext->setStrokeThickness(thickness); graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan); break; @@ -1341,6 +1338,50 @@ void RenderObject::showTreeForThis() const node()->showTreeForThis(); } +void RenderObject::showRenderObject() const +{ + showRenderObject(0); +} + +void RenderObject::showRenderObject(int printedCharacters) const +{ + // As this function is intended to be used when debugging, the + // this pointer may be 0. + if (!this) { + fputs("(null)\n", stderr); + return; + } + + printedCharacters += fprintf(stderr, "%s %p", renderName(), this); + + if (node()) { + if (printedCharacters) + for (; printedCharacters < 39; printedCharacters++) + fputc(' ', stderr); + fputc('\t', stderr); + node()->showNode(); + } else + fputc('\n', stderr); +} + +void RenderObject::showRenderTreeAndMark(const RenderObject* markedObject1, const char* markedLabel1, const RenderObject* markedObject2, const char* markedLabel2, int depth) const +{ + int printedCharacters = 0; + if (markedObject1 == this && markedLabel1) + printedCharacters += fprintf(stderr, "%s", markedLabel1); + if (markedObject2 == this && markedLabel2) + printedCharacters += fprintf(stderr, "%s", markedLabel2); + for (; printedCharacters < depth * 2; printedCharacters++) + fputc(' ', stderr); + + showRenderObject(printedCharacters); + if (!this) + return; + + for (const RenderObject* child = firstChild(); child; child = child->nextSibling()) + child->showRenderTreeAndMark(markedObject1, markedLabel1, markedObject2, markedLabel2, depth + 1); +} + #endif // NDEBUG Color RenderObject::selectionBackgroundColor() const @@ -2372,9 +2413,20 @@ RenderBoxModelObject* RenderObject::offsetParent() const VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity) { - // If this is a non-anonymous renderer, then it's simple. - if (Node* node = this->node()) + // If this is a non-anonymous renderer in an editable area, then it's simple. + if (Node* node = this->node()) { + if (!node->isContentEditable()) { + // If it can be found, we prefer a visually equivalent position that is editable. + Position position(node, offset); + Position candidate = position.downstream(Position::CanCrossEditingBoundary); + if (candidate.node()->isContentEditable()) + return VisiblePosition(candidate, affinity); + candidate = position.upstream(Position::CanCrossEditingBoundary); + if (candidate.node()->isContentEditable()) + return VisiblePosition(candidate, affinity); + } return VisiblePosition(node, offset, affinity); + } // We don't want to cross the boundary between editable and non-editable // regions of the document, but that is either impossible or at least @@ -2476,4 +2528,19 @@ void showTree(const WebCore::RenderObject* ro) ro->showTreeForThis(); } +void showRenderTree(const WebCore::RenderObject* object1) +{ + showRenderTree(object1, 0); +} + +void showRenderTree(const WebCore::RenderObject* object1, const WebCore::RenderObject* object2) +{ + if (object1) { + const WebCore::RenderObject* root = object1; + while (root->parent()) + root = root->parent(); + root->showRenderTreeAndMark(object1, "*", object2, "-", 0); + } +} + #endif diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index e358c98..d40ae6d 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -4,6 +4,7 @@ * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google 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 @@ -76,11 +77,13 @@ enum PaintPhase { PaintPhaseMask }; -enum PaintRestriction { - PaintRestrictionNone, - PaintRestrictionSelectionOnly, - PaintRestrictionSelectionOnlyBlackText +enum PaintBehaviorFlags { + PaintBehaviorNormal = 0, + PaintBehaviorSelectionOnly = 1 << 0, + PaintBehaviorForceBlackText = 1 << 1, + PaintBehaviorFlattenCompositingLayers = 1 << 2 }; +typedef unsigned PaintBehavior; enum HitTestFilter { HitTestAll, @@ -228,6 +231,12 @@ private: public: #ifndef NDEBUG void showTreeForThis() const; + + void showRenderObject() const; + // We don't make printedCharacters an optional parameter so that + // showRenderObject can be called from gdb easily. + void showRenderObject(int printedCharacters) const; + void showRenderTreeAndMark(const RenderObject* markedObject1 = 0, const char* markedLabel1 = 0, const RenderObject* markedObject2 = 0, const char* markedLabel2 = 0, int depth = 0) const; #endif static RenderObject* createObject(Node*, RenderStyle*); @@ -252,6 +261,7 @@ public: virtual bool isBoxModelObject() const { return false; } virtual bool isCounter() const { return false; } virtual bool isFieldset() const { return false; } + virtual bool isFileUploadControl() const { return false; } virtual bool isFrame() const { return false; } virtual bool isFrameSet() const { return false; } virtual bool isImage() const { return false; } @@ -267,6 +277,10 @@ public: virtual bool isRenderInline() const { return false; } virtual bool isRenderPart() const { return false; } virtual bool isRenderView() const { return false; } + virtual bool isRuby() const { return false; } + virtual bool isRubyBase() const { return false; } + virtual bool isRubyRun() const { return false; } + virtual bool isRubyText() const { return false; } virtual bool isSlider() const { return false; } virtual bool isTable() const { return false; } virtual bool isTableCell() const { return false; } @@ -1028,6 +1042,10 @@ inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* render #ifndef NDEBUG // Outside the WebCore namespace for ease of invocation from gdb. void showTree(const WebCore::RenderObject*); +void showRenderTree(const WebCore::RenderObject* object1); +// We don't make object2 an optional parameter so that showRenderTree +// can be called from gdb easily. +void showRenderTree(const WebCore::RenderObject* object1, const WebCore::RenderObject* object2); #endif #endif // RenderObject_h diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp index 23ab98f..d56a015 100644 --- a/WebCore/rendering/RenderObjectChildList.cpp +++ b/WebCore/rendering/RenderObjectChildList.cpp @@ -271,24 +271,29 @@ static RenderObject* findBeforeAfterParent(RenderObject* object) return beforeAfterParent; } -static void invalidateCountersInContainer(RenderObject* container) +static void invalidateCountersInContainer(RenderObject* container, const AtomicString& identifier) { if (!container) return; container = findBeforeAfterParent(container); if (!container) return; + // Sometimes the counter is attached directly on the container. + if (container->isCounter()) { + toRenderCounter(container)->invalidate(identifier); + return; + } for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) { if (content->isCounter()) - toRenderCounter(content)->invalidate(); + toRenderCounter(content)->invalidate(identifier); } } -void RenderObjectChildList::invalidateCounters(RenderObject* owner) +void RenderObjectChildList::invalidateCounters(RenderObject* owner, const AtomicString& identifier) { ASSERT(!owner->documentBeingDestroyed()); - invalidateCountersInContainer(beforeAfterContainer(owner, BEFORE)); - invalidateCountersInContainer(beforeAfterContainer(owner, AFTER)); + invalidateCountersInContainer(beforeAfterContainer(owner, BEFORE), identifier); + invalidateCountersInContainer(beforeAfterContainer(owner, AFTER), identifier); } void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject) @@ -369,9 +374,11 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo RefPtr<RenderStyle> style = RenderStyle::create(); style->inheritFrom(pseudoElementStyle); genChild->setStyle(style.release()); - } else - // Must be a first-letter container. updateFirstLetter() will take care of it. - ASSERT(genChild->style()->styleType() == FIRST_LETTER); + } else { + // RenderListItem may insert a list marker here. We do not need to care about this case. + // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it. + ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER); + } } } return; // We've updated the generated content. That's all we needed to do. diff --git a/WebCore/rendering/RenderObjectChildList.h b/WebCore/rendering/RenderObjectChildList.h index bf8800a..ba73c50 100644 --- a/WebCore/rendering/RenderObjectChildList.h +++ b/WebCore/rendering/RenderObjectChildList.h @@ -30,6 +30,7 @@ namespace WebCore { +class AtomicString; class RenderObject; class RenderObjectChildList { @@ -55,7 +56,7 @@ public: void insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* before, bool fullInsert = true); void updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject = 0); - void invalidateCounters(RenderObject* owner); + void invalidateCounters(RenderObject* owner, const AtomicString& identifier); private: RenderObject* m_firstChild; diff --git a/WebCore/rendering/RenderOverflow.h b/WebCore/rendering/RenderOverflow.h index ed8976a..253a672 100644 --- a/WebCore/rendering/RenderOverflow.h +++ b/WebCore/rendering/RenderOverflow.h @@ -37,7 +37,7 @@ namespace WebCore // Examples of visual overflow are shadows, text stroke (and eventually outline and border-image). // This object is allocated only when some of these fields have non-default values in the owning box. -class RenderOverflow { +class RenderOverflow : public Noncopyable { public: RenderOverflow(const IntRect& defaultRect = IntRect()) : m_topLayoutOverflow(defaultRect.y()) diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index 27d2e72..ba579df 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -153,7 +153,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty) if (drawSelectionTint) { IntRect selectionPaintingRect = localSelectionRect(); selectionPaintingRect.move(tx, ty); - paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor()); + paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor(), style()->colorSpace()); } } diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp index 5fa3c62..1d589ae 100644 --- a/WebCore/rendering/RenderReplica.cpp +++ b/WebCore/rendering/RenderReplica.cpp @@ -72,7 +72,7 @@ void RenderReplica::paint(PaintInfo& paintInfo, int tx, int ty) // computing using the wrong rootLayer layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(), paintInfo.context, paintInfo.rect, - PaintRestrictionNone, 0, 0, + PaintBehaviorNormal, 0, 0, RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection); else if (paintInfo.phase == PaintPhaseMask) paintMask(paintInfo, tx, ty); diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp new file mode 100644 index 0000000..8d113f9 --- /dev/null +++ b/WebCore/rendering/RenderRuby.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "RenderRuby.h" + +#include "RenderRubyRun.h" + +namespace WebCore { + +//=== generic helper functions to avoid excessive code duplication === + +static RenderRubyRun* lastRubyRun(const RenderObject* ruby) +{ + RenderObject* child = ruby->lastChild(); + if (child && ruby->isAfterContent(child)) + child = child->previousSibling(); + ASSERT(!child || child->isRubyRun()); + return static_cast<RenderRubyRun*>(child); +} + +static inline RenderRubyRun* findRubyRunParent(RenderObject* child) +{ + while (child && !child->isRubyRun()) + child = child->parent(); + return static_cast<RenderRubyRun*>(child); +} + +//=== ruby as inline object === + +RenderRubyAsInline::RenderRubyAsInline(Node* node) + : RenderInline(node) +{ +} + +RenderRubyAsInline::~RenderRubyAsInline() +{ +} + +bool RenderRubyAsInline::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->isRubyText() + || child->isRubyRun() + || child->isInline(); +} + +void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild) +{ + // Note: ':after' content is handled implicitely below + + // if child is a ruby run, just add it normally + if (child->isRubyRun()) { + RenderInline::addChild(child, beforeChild); + return; + } + + if (beforeChild && !isAfterContent(beforeChild)) { + // insert child into run + ASSERT(!beforeChild->isRubyRun()); + RenderRubyRun* run = findRubyRunParent(beforeChild); + ASSERT(run); // beforeChild should always have a run as parent + if (run) { + run->addChild(child, beforeChild); + return; + } + ASSERT(false); // beforeChild should always have a run as parent! + // Emergency fallback: fall through and just append. + } + + // If the new child would be appended, try to add the child to the previous run + // if possible, or create a new run otherwise. + // (The RenderRubyRun object will handle the details) + RenderRubyRun* lastRun = lastRubyRun(this); + if (!lastRun || lastRun->hasRubyText()) { + lastRun = RenderRubyRun::staticCreateRubyRun(this); + RenderInline::addChild(lastRun); + } + lastRun->addChild(child); +} + +void RenderRubyAsInline::removeChild(RenderObject* child) +{ + // If the child's parent is *this, i.e. a ruby run or ':after' content, + // just use the normal remove method. + if (child->parent() == this) { + ASSERT(child->isRubyRun() || child->isAfterContent()); + RenderInline::removeChild(child); + return; + } + + // Find the containing run + RenderRubyRun* run = findRubyRunParent(child); + ASSERT(run); + run->removeChild(child); +} + + +//=== ruby as block object === + +RenderRubyAsBlock::RenderRubyAsBlock(Node* node) + : RenderBlock(node) +{ +} + +RenderRubyAsBlock::~RenderRubyAsBlock() +{ +} + +bool RenderRubyAsBlock::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->isRubyText() + || child->isRubyRun() + || child->isInline(); +} + +void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild) +{ + // Note: ':after' content is handled implicitely below + + // if child is a ruby run, just add it normally + if (child->isRubyRun()) { + RenderBlock::addChild(child, beforeChild); + return; + } + + if (beforeChild && !isAfterContent(beforeChild)) { + // insert child into run + ASSERT(!beforeChild->isRubyRun()); + RenderObject* run = beforeChild; + while (run && !run->isRubyRun()) + run = run->parent(); + if (run) { + run->addChild(child, beforeChild); + return; + } + ASSERT(false); // beforeChild should always have a run as parent! + // Emergency fallback: fall through and just append. + } + + // If the new child would be appended, try to add the child to the previous run + // if possible, or create a new run otherwise. + // (The RenderRubyRun object will handle the details) + RenderRubyRun* lastRun = lastRubyRun(this); + if (!lastRun || lastRun->hasRubyText()) { + lastRun = RenderRubyRun::staticCreateRubyRun(this); + RenderBlock::addChild(lastRun); + } + lastRun->addChild(child); +} + +void RenderRubyAsBlock::removeChild(RenderObject* child) +{ + // If the child's parent is *this, just use the normal remove method. + if (child->parent() == this) { + // This should happen only during destruction of the whole ruby element, though. + RenderBlock::removeChild(child); + return; + } + + // Find the containing run + RenderRubyRun* run = findRubyRunParent(child); + ASSERT(run); + run->removeChild(child); +} + +} // namespace WebCore + diff --git a/WebCore/rendering/RenderRuby.h b/WebCore/rendering/RenderRuby.h new file mode 100644 index 0000000..a74150c --- /dev/null +++ b/WebCore/rendering/RenderRuby.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 RenderRuby_h +#define RenderRuby_h + +#include "RenderBlock.h" +#include "RenderInline.h" + +namespace WebCore { + +// Following the HTML 5 spec, the box object model for a <ruby> element allows several runs of ruby +// bases with their respective ruby texts looks as follows: +// +// 1 RenderRuby object, corresponding to the whole <ruby> HTML element +// 1+ RenderRubyRun (anonymous) +// 0 or 1 RenderRubyText - shuffled to the front in order to re-use existing block layouting +// 0-n inline object(s) +// 0 or 1 RenderRubyBase - contains the inline objects that make up the ruby base +// 1-n inline object(s) +// +// Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer. + +// <ruby> when used as 'display:inline' +class RenderRubyAsInline : public RenderInline { +public: + RenderRubyAsInline(Node*); + virtual ~RenderRubyAsInline(); + + virtual const char* renderName() const { return "RenderRuby (inline)"; } + + virtual bool isRuby() const { return true; } + + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void removeChild(RenderObject* child); +}; + +// <ruby> when used as 'display:block' or 'display:inline-block' +class RenderRubyAsBlock : public RenderBlock { +public: + RenderRubyAsBlock(Node*); + virtual ~RenderRubyAsBlock(); + + virtual const char* renderName() const { return "RenderRuby (block)"; } + + virtual bool isRuby() const { return true; } + + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void removeChild(RenderObject* child); +}; + +} // namespace WebCore + +#endif // RenderRuby_h diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp new file mode 100644 index 0000000..5cb25f4 --- /dev/null +++ b/WebCore/rendering/RenderRubyBase.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "RenderRubyBase.h" + +namespace WebCore { + +RenderRubyBase::RenderRubyBase(Node* node) + : RenderBlock(node) +{ + setInline(false); +} + +RenderRubyBase::~RenderRubyBase() +{ +} + +bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->isInline(); +} + +void RenderRubyBase::splitToLeft(RenderBlock* leftBase, RenderObject* beforeChild) +{ + // This function removes all children that are before (!) beforeChild + // and appends them to leftBase. + ASSERT(leftBase); + + // First make sure that beforeChild (if set) is indeed a direct child of this. + // Fallback: climb up the tree to make sure. This may result in somewhat incorrect rendering. + // FIXME: Can this happen? Is there a better/more correct way to solve this? + ASSERT(!beforeChild || beforeChild->parent() == this); + while (beforeChild && beforeChild->parent() != this) + beforeChild = beforeChild->parent(); + + RenderObject* child = firstChild(); + while (child != beforeChild) { + RenderObject* nextChild = child->nextSibling(); + moveChildTo(leftBase, leftBase->children(), child); + child = nextChild; + } +} + +void RenderRubyBase::mergeWithRight(RenderBlock* rightBase) +{ + // This function removes all children and prepends (!) them to rightBase. + ASSERT(rightBase); + + RenderObject* firstPos = rightBase->firstChild(); + RenderObject* child = lastChild(); + while (child) { + moveChildTo(rightBase, rightBase->children(), firstPos, child); + firstPos = child; + child = lastChild(); + } +} + +} // namespace WebCore diff --git a/WebCore/rendering/RenderRubyBase.h b/WebCore/rendering/RenderRubyBase.h new file mode 100644 index 0000000..57baf99 --- /dev/null +++ b/WebCore/rendering/RenderRubyBase.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 RenderRubyBase_h +#define RenderRubyBase_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderRubyBase : public RenderBlock { +public: + RenderRubyBase(Node*); + virtual ~RenderRubyBase(); + + virtual const char* renderName() const { return "RenderRubyBase (anonymous)"; } + + virtual bool isRubyBase() const { return true; } + + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + + void splitToLeft(RenderBlock* leftBase, RenderObject* beforeChild); + void mergeWithRight(RenderBlock* rightBase); +}; + +} // namespace WebCore + +#endif // RenderRubyBase_h diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp new file mode 100644 index 0000000..8578c55 --- /dev/null +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "RenderRubyRun.h" + +#include "RenderRubyBase.h" +#include "RenderRubyText.h" +#include "RenderView.h" + +using namespace std; + +namespace WebCore { + +RenderRubyRun::RenderRubyRun(Node* node) + : RenderBlock(node) + , m_beingDestroyed(false) +{ + setReplaced(true); + setInline(true); +} + +RenderRubyRun::~RenderRubyRun() +{ +} + +void RenderRubyRun::destroy() +{ + // Mark if the run is being destroyed to avoid trouble in removeChild(). + m_beingDestroyed = true; + RenderBlock::destroy(); +} + +bool RenderRubyRun::hasRubyText() const +{ + // The only place where a ruby text can be is in the first position + // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves. + return firstChild() && firstChild()->isRubyText(); +} + +bool RenderRubyRun::hasRubyBase() const +{ + // The only place where a ruby base can be is in the last position + // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves. + return lastChild() && lastChild()->isRubyBase(); +} + +bool RenderRubyRun::isEmpty() const +{ + return !hasRubyText() && !hasRubyBase(); +} + +RenderRubyText* RenderRubyRun::rubyText() const +{ + RenderObject* child = firstChild(); + return child && child->isRubyText() ? static_cast<RenderRubyText*>(child) : 0; +} + +RenderRubyBase* RenderRubyRun::rubyBase() const +{ + RenderObject* child = lastChild(); + return child && child->isRubyBase() ? static_cast<RenderRubyBase*>(child) : 0; +} + +RenderRubyBase* RenderRubyRun::rubyBaseSafe() +{ + RenderRubyBase* base = rubyBase(); + if (!base) { + base = createRubyBase(); + RenderBlock::addChild(base); + } + return base; +} + +RenderBlock* RenderRubyRun::firstLineBlock() const +{ + return 0; +} + +void RenderRubyRun::updateFirstLetter() +{ +} + +bool RenderRubyRun::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->isRubyText() || child->isInline(); +} + +void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild) +{ + ASSERT(child); + + // If child is a ruby text + if (child->isRubyText()) { + if (!beforeChild) { + // RenderRuby has already ascertained that we can add the child here. + ASSERT(!hasRubyText()); + // prepend ruby texts as first child + RenderBlock::addChild(child, firstChild()); + } else if (beforeChild->isRubyText()) { + // New text is inserted just before another. + // In this case the new text takes the place of the old one, and + // the old text goes into a new run that is inserted as next sibling. + ASSERT(beforeChild->parent() == this); + RenderObject* ruby = parent(); + ASSERT(ruby->isRuby()); + RenderBlock* newRun = staticCreateRubyRun(ruby); + ruby->addChild(newRun, nextSibling()); + // Add the new ruby text and move the old one to the new run + // Note: Doing it in this order and not using RenderRubyRun's methods, + // in order to avoid automatic removal of the ruby run in case there is no + // other child besides the old ruby text. + RenderBlock::addChild(child, beforeChild); + RenderBlock::removeChild(beforeChild); + newRun->addChild(beforeChild); + } else { + ASSERT(hasRubyBase()); // Otherwise beforeChild would be borked. + // Insertion before a ruby base object. + // In this case we need insert a new run before the current one and split the base. + RenderObject* ruby = parent(); + RenderRubyRun* newRun = staticCreateRubyRun(ruby); + ruby->addChild(newRun, this); + newRun->addChild(child); + rubyBaseSafe()->splitToLeft(newRun->rubyBaseSafe(), beforeChild); + } + } else { + // child is not a text -> insert it into the base + // (append it instead if beforeChild is the ruby text) + if (beforeChild && beforeChild->isRubyText()) + beforeChild = 0; + rubyBaseSafe()->addChild(child, beforeChild); + } +} + +void RenderRubyRun::removeChild(RenderObject* child) +{ + // If the child is a ruby text, then merge the ruby base with the base of + // the right sibling run, if possible. + if (!m_beingDestroyed && !documentBeingDestroyed() && child->isRubyText()) { + RenderRubyBase* base = rubyBase(); + RenderObject* rightNeighbour = nextSibling(); + if (base && rightNeighbour && rightNeighbour->isRubyRun()) { + // Ruby run without a base can happen only at the first run. + RenderRubyRun* rightRun = static_cast<RenderRubyRun*>(rightNeighbour); + ASSERT(rightRun->hasRubyBase()); + base->mergeWithRight(rightRun->rubyBaseSafe()); + // The now empty ruby base will be removed below. + } + } + + RenderBlock::removeChild(child); + + if (!m_beingDestroyed && !documentBeingDestroyed()) { + // Check if our base (if any) is now empty. If so, destroy it. + RenderBlock* base = rubyBase(); + if (base && !base->firstChild()) { + RenderBlock::removeChild(base); + base->deleteLineBoxTree(); + base->destroy(); + } + + // If any of the above leaves the run empty, destroy it as well. + if (isEmpty()) { + parent()->removeChild(this); + deleteLineBoxTree(); + destroy(); + } + } +} + +RenderRubyBase* RenderRubyRun::createRubyBase() const +{ + RenderRubyBase* rb = new (renderArena()) RenderRubyBase(document() /* anonymous */); + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(style()); + newStyle->setDisplay(BLOCK); + newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER? + rb->setStyle(newStyle.release()); + return rb; +} + +RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby) +{ + ASSERT(parentRuby && parentRuby->isRuby()); + RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun(parentRuby->document() /* anonymous */); + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + newStyle->inheritFrom(parentRuby->style()); + newStyle->setDisplay(INLINE_BLOCK); + rr->setStyle(newStyle.release()); + return rr; +} + +} // namespace WebCore diff --git a/WebCore/rendering/RenderRubyRun.h b/WebCore/rendering/RenderRubyRun.h new file mode 100644 index 0000000..361dfe5 --- /dev/null +++ b/WebCore/rendering/RenderRubyRun.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 RenderRubyRun_h +#define RenderRubyRun_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderRubyBase; +class RenderRubyText; + +// RenderRubyRun are 'inline-block/table' like objects,and wrap a single pairing of a ruby base with its ruby text(s). +// See RenderRuby.h for further comments on the structure + +class RenderRubyRun : public RenderBlock { +public: + RenderRubyRun(Node*); + virtual ~RenderRubyRun(); + + virtual void destroy(); + + virtual const char* renderName() const { return "RenderRubyRun (anonymous)"; } + + virtual bool isRubyRun() const { return true; } + + bool hasRubyText() const; + bool hasRubyBase() const; + bool isEmpty() const; + RenderRubyText* rubyText() const; + RenderRubyBase* rubyBase() const; + RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist + + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void removeChild(RenderObject* child); + + virtual RenderBlock* firstLineBlock() const; + virtual void updateFirstLetter(); + + static RenderRubyRun* staticCreateRubyRun(const RenderObject* parentRuby); + +protected: + RenderRubyBase* createRubyBase() const; + +private: + bool m_beingDestroyed; +}; + +} // namespace WebCore + +#endif // RenderRubyRun_h diff --git a/WebCore/rendering/RenderRubyText.cpp b/WebCore/rendering/RenderRubyText.cpp new file mode 100644 index 0000000..cfe3b5c --- /dev/null +++ b/WebCore/rendering/RenderRubyText.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "RenderRubyText.h" + +namespace WebCore { + +RenderRubyText::RenderRubyText(Node* node) + : RenderBlock(node) +{ +} + +RenderRubyText::~RenderRubyText() +{ +} + +bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const +{ + return child->isInline(); +} + +} // namespace WebCore diff --git a/WebCore/rendering/RenderRubyText.h b/WebCore/rendering/RenderRubyText.h new file mode 100644 index 0000000..e475914 --- /dev/null +++ b/WebCore/rendering/RenderRubyText.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 RenderRubyText_h +#define RenderRubyText_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderRubyText : public RenderBlock { +public: + RenderRubyText(Node*); + virtual ~RenderRubyText(); + + virtual const char* renderName() const { return "RenderRubyText"; } + + virtual bool isRubyText() const { return true; } + + virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; +}; + +} // namespace WebCore + +#endif // RenderRubyText_h diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 7e0b40d..41a1a10 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -166,7 +166,7 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) if (imageElt->preserveAspectRatio()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE) adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio()); - paintInfo.context->drawImage(image(), destRect, srcRect); + paintInfo.context->drawImage(image(), DeviceColorSpace, destRect, srcRect); finishRenderSVGContent(this, paintInfo, filter, savedInfo.context); } diff --git a/WebCore/rendering/RenderScrollbarTheme.cpp b/WebCore/rendering/RenderScrollbarTheme.cpp index 06ca32a..19143cc 100644 --- a/WebCore/rendering/RenderScrollbarTheme.cpp +++ b/WebCore/rendering/RenderScrollbarTheme.cpp @@ -109,7 +109,7 @@ IntRect RenderScrollbarTheme::constrainTrackRectToTrackPieces(Scrollbar* scrollb void RenderScrollbarTheme::paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect) { // FIXME: Implement. - context->fillRect(cornerRect, Color::white); + context->fillRect(cornerRect, Color::white, DeviceColorSpace); } void RenderScrollbarTheme::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar) diff --git a/WebCore/rendering/RenderSelectionInfo.h b/WebCore/rendering/RenderSelectionInfo.h index e7b7b78..c06a9ae 100644 --- a/WebCore/rendering/RenderSelectionInfo.h +++ b/WebCore/rendering/RenderSelectionInfo.h @@ -30,7 +30,7 @@ namespace WebCore { -class RenderSelectionInfoBase { +class RenderSelectionInfoBase : public Noncopyable { public: RenderSelectionInfoBase() : m_object(0) diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index c8b60fd..7398a2f 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -52,7 +52,8 @@ 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 isIntegral; + bool hasStep; + double step; double minimum; double maximum; // maximum must be >= minimum. @@ -79,19 +80,28 @@ struct SliderRange { SliderRange::SliderRange(HTMLInputElement* element) { - // FIXME: What's the right way to handle an integral range with non-integral minimum and maximum? - // Currently values are guaranteed to be integral but could be outside the range in that case. - - isIntegral = !equalIgnoringCase(element->getAttribute(precisionAttr), "float"); - - maximum = element->rangeMaximum(); - minimum = element->rangeMinimum(); + 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)); - return isIntegral ? round(clampedValue) : clampedValue; + 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) @@ -356,10 +366,9 @@ void RenderSlider::layout() thumb->repaintDuringLayoutIfMoved(oldThumbRect); statePusher.pop(); + addOverflowFromChild(thumb); } - addOverflowFromChild(thumb); - repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -374,7 +383,7 @@ void RenderSlider::updateFromElement() bool clamped; double value = range.valueFromElement(element, &clamped); if (clamped) - element->setValueFromRenderer(String::number(value)); + element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); // Layout will take care of the thumb's size and position. if (!m_thumb) { @@ -430,7 +439,7 @@ void RenderSlider::setValueForPosition(int position) if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); - element->setValueFromRenderer(String::number(value)); + element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); // Also update the position if appropriate. if (position != currentPosition()) { diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 8e0b613..4e7036e 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -168,6 +168,17 @@ void RenderTableCell::setOverrideSize(int size) RenderBlock::setOverrideSize(size); } +IntSize RenderTableCell::offsetFromContainer(RenderObject* o) const +{ + ASSERT(o == container()); + + IntSize offset = RenderBlock::offsetFromContainer(o); + if (parent()) + offset.expand(-parentBox()->x(), -parentBox()->y()); + + return offset; +} + IntRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { // If the table grid is dirty, we cannot get reliable information about adjoining cells, @@ -231,30 +242,6 @@ void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContain RenderBlock::computeRectForRepaint(repaintContainer, r, fixed); } -void RenderTableCell::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const -{ - if (repaintContainer == this) - return; - - RenderView* v = view(); - if ((!v || !v->layoutStateEnabled()) && parent()) { - // Rows are in the same coordinate space, so don't add their offset in. - // FIXME: this is wrong with transforms - transformState.move(-parentBox()->x(), -parentBox()->y()); - } - RenderBlock::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); -} - -void RenderTableCell::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const -{ - RenderBlock::mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); - if (parent()) { - // Rows are in the same coordinate space, so add their offset back in. - // FIXME: this is wrong with transforms - transformState.move(parentBox()->x(), parentBox()->y()); - } -} - int RenderTableCell::baselinePosition(bool firstLine, bool isRootLineBox) const { if (isRootLineBox) diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 9532bb6..f285198 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -110,9 +110,6 @@ protected: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; - virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; - private: virtual const char* renderName() const { return isAnonymous() ? "RenderTableCell (anonymous)" : "RenderTableCell"; } @@ -127,6 +124,7 @@ private: virtual void paintBoxDecorations(PaintInfo&, int tx, int ty); virtual void paintMask(PaintInfo&, int tx, int ty); + virtual IntSize offsetFromContainer(RenderObject*) const; virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index bafadfc..a11a14b 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1997 Martin Jones (mjones@kde.org) * (C) 1997 Torben Weis (weis@kde.org) * (C) 1998 Waldo Bastian (bastian@kde.org) diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 5052c3a..b627afe 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -46,6 +46,14 @@ namespace WebCore { using namespace HTMLNames; +static inline void setRowHeightToRowStyleHeightIfNotRelative(RenderTableSection::RowStruct* row) +{ + ASSERT(row && row->rowRenderer); + row->height = row->rowRenderer->style()->height(); + if (row->height.isRelative()) + row->height = Length(); +} + RenderTableSection::RenderTableSection(Node* node) : RenderBox(node) , m_gridRows(0) @@ -126,11 +134,8 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild m_grid[m_cRow].rowRenderer = toRenderTableRow(child); - if (!beforeChild) { - m_grid[m_cRow].height = child->style()->height(); - if (m_grid[m_cRow].height.isRelative()) - m_grid[m_cRow].height = Length(); - } + if (!beforeChild) + setRowHeightToRowStyleHeightIfNotRelative(&m_grid[m_cRow]); // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that. while (beforeChild && beforeChild->parent() != this) @@ -1190,6 +1195,7 @@ void RenderTableSection::recalcCells() RenderTableRow* tableRow = toRenderTableRow(row); m_grid[m_cRow].rowRenderer = tableRow; + setRowHeightToRowStyleHeightIfNotRelative(&m_grid[m_cRow]); for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) { if (cell->isTableCell()) diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 40c3d75..95aa277 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -757,6 +757,17 @@ void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& f setPrefWidthsDirty(false); } +bool RenderText::isAllCollapsibleWhitespace() +{ + int length = textLength(); + const UChar* text = characters(); + for (int i = 0; i < length; i++) { + if (!style()->isCollapsibleWhiteSpace(text[i])) + return false; + } + return true; +} + bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const { unsigned currPos; @@ -813,7 +824,9 @@ void RenderText::setSelectionState(SelectionState state) } } - containingBlock()->setSelectionState(state); + // The returned value can be null in case of an orphaned tree. + if (RenderBlock* cb = containingBlock()) + cb->setSelectionState(state); } void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force) diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h index 915ff40..d46bce9 100644 --- a/WebCore/rendering/RenderText.h +++ b/WebCore/rendering/RenderText.h @@ -121,7 +121,8 @@ public: void checkConsistency() const; virtual void calcPrefWidths(int leadWidth); - + bool isAllCollapsibleWhitespace(); + protected: virtual void styleWillChange(StyleDifference, const RenderStyle*) { } virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index f430399..b258597 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -70,8 +70,8 @@ static Color disabledTextColor(const Color& textColor, const Color& backgroundCo RenderTextControl::RenderTextControl(Node* node, bool placeholderVisible) : RenderBlock(node) , m_placeholderVisible(placeholderVisible) - , m_edited(false) - , m_userEdited(false) + , m_wasChangedSinceLastChangeEvent(false) + , m_lastChangeWasUserEdit(false) { } @@ -195,17 +195,17 @@ void RenderTextControl::setInnerTextValue(const String& innerTextValue) ASSERT(!ec); } - m_edited = false; - m_userEdited = false; + // We set m_lastChangeWasUserEdit to false since this change was not explicty made by the user (say, via typing on the keyboard), see <rdar://problem/5359921>. + m_lastChangeWasUserEdit = false; } static_cast<Element*>(node())->setFormControlValueMatchesRenderer(true); } -void RenderTextControl::setUserEdited(bool isUserEdited) +void RenderTextControl::setLastChangeWasUserEdit(bool lastChangeWasUserEdit) { - m_userEdited = isUserEdited; - document()->setIgnoreAutofocus(isUserEdited); + m_lastChangeWasUserEdit = lastChangeWasUserEdit; + document()->setIgnoreAutofocus(lastChangeWasUserEdit); } int RenderTextControl::selectionStart() @@ -312,8 +312,8 @@ int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos) void RenderTextControl::subtreeHasChanged() { - m_edited = true; - m_userEdited = true; + m_wasChangedSinceLastChangeEvent = true; + m_lastChangeWasUserEdit = true; } String RenderTextControl::finishText(Vector<UChar>& result) const diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index cdd8716..394eb9c 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -34,11 +34,11 @@ class RenderTextControl : public RenderBlock { public: virtual ~RenderTextControl(); - bool isEdited() const { return m_edited; } - void setEdited(bool isEdited) { m_edited = isEdited; } + bool wasChangedSinceLastChangeEvent() const { return m_wasChangedSinceLastChangeEvent; } + void setChangedSinceLastChangeEvent(bool wasChangedSinceLastChangeEvent) { m_wasChangedSinceLastChangeEvent = wasChangedSinceLastChangeEvent; } - bool isUserEdited() const { return m_userEdited; } - void setUserEdited(bool isUserEdited); + bool lastChangeWasUserEdit() const { return m_lastChangeWasUserEdit; } + void setLastChangeWasUserEdit(bool lastChangeWasUserEdit); int selectionStart(); int selectionEnd(); @@ -105,8 +105,8 @@ private: String finishText(Vector<UChar>&) const; - bool m_edited; - bool m_userEdited; + bool m_wasChangedSinceLastChangeEvent; + bool m_lastChangeWasUserEdit; RefPtr<TextControlInnerTextElement> m_innerText; }; diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 6ff9235..afc3edd 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -67,8 +67,8 @@ bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitT return false; bool resultIsTextValueOrPlaceholder - = !m_placeholderVisible && result.innerNode() == innerTextElement() - || m_placeholderVisible && result.innerNode()->isDescendantOf(innerTextElement()); + = (!m_placeholderVisible && result.innerNode() == innerTextElement()) + || (m_placeholderVisible && result.innerNode()->isDescendantOf(innerTextElement())); if (result.innerNode() == node() || resultIsTextValueOrPlaceholder) hitInnerTextElement(result, x, y, tx, ty); diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index dd1c24c..56d4363 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -150,7 +150,7 @@ void RenderTextControlSingleLine::hidePopup() void RenderTextControlSingleLine::subtreeHasChanged() { - bool wasEdited = isEdited(); + bool wasChanged = wasChangedSinceLastChangeEvent(); RenderTextControl::subtreeHasChanged(); InputElement* input = inputElement(); @@ -167,7 +167,7 @@ void RenderTextControlSingleLine::subtreeHasChanged() if (input->searchEventsShouldBeDispatched()) startSearchEventTimer(); - if (!wasEdited && node()->focused()) { + if (!wasChanged && node()->focused()) { if (Frame* frame = document()->frame()) frame->textFieldDidBeginEditing(static_cast<Element*>(node())); } diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index 238279a..f6afb77 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -1,7 +1,7 @@ /** * This file is part of the theme implementation for form controls in WebCore. * - * Copyright (C) 2005, 2006, 2007, 2008 Apple Computer, Inc. + * Copyright (C) 2005, 2006, 2007, 2008, 2009 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 @@ -282,6 +282,8 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf return paintMediaRewindButton(o, paintInfo, r); case MediaReturnToRealtimeButtonPart: return paintMediaReturnToRealtimeButton(o, paintInfo, r); + case MediaToggleClosedCaptionsButtonPart: + return paintMediaToggleClosedCaptionsButton(o, paintInfo, r); case MediaSliderPart: return paintMediaSliderTrack(o, paintInfo, r); case MediaSliderThumbPart: @@ -420,6 +422,8 @@ bool RenderTheme::shouldRenderMediaControlPart(ControlPart part, Element* e) return mediaElement->movieLoadType() == MediaPlayer::LiveStream; case MediaFullscreenButtonPart: return mediaElement->supportsFullscreen(); + case MediaToggleClosedCaptionsButtonPart: + return mediaElement->hasClosedCaptions(); default: return true; } @@ -705,6 +709,10 @@ bool RenderTheme::isHovered(const RenderObject* o) const bool RenderTheme::isDefault(const RenderObject* o) const { + // A button should only have the default appearance if the page is active + if (!isActive(o)) + return false; + if (!o->document()) return false; diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 68e2eba..ee359d7 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -253,6 +253,7 @@ protected: virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaRewindButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } + virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } virtual bool paintMediaTimeRemaining(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; } diff --git a/WebCore/rendering/RenderThemeChromiumLinux.cpp b/WebCore/rendering/RenderThemeChromiumLinux.cpp index 9048ce3..4b09174 100644 --- a/WebCore/rendering/RenderThemeChromiumLinux.cpp +++ b/WebCore/rendering/RenderThemeChromiumLinux.cpp @@ -32,6 +32,10 @@ namespace WebCore { +unsigned RenderThemeChromiumLinux::m_thumbInactiveColor = 0xf0ebe5; +unsigned RenderThemeChromiumLinux::m_thumbActiveColor = 0xfaf8f5; +unsigned RenderThemeChromiumLinux::m_trackColor = 0xe3ddd8; + PassRefPtr<RenderTheme> RenderThemeChromiumLinux::create() { return adoptRef(new RenderThemeChromiumLinux()); @@ -122,4 +126,12 @@ double RenderThemeChromiumLinux::caretBlinkIntervalInternal() const return m_caretBlinkInterval; } +void RenderThemeChromiumLinux::setScrollbarColors( + SkColor inactiveColor, SkColor activeColor, SkColor trackColor) +{ + m_thumbInactiveColor = inactiveColor; + m_thumbActiveColor = activeColor; + m_trackColor = trackColor; +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumLinux.h b/WebCore/rendering/RenderThemeChromiumLinux.h index e137ad5..8736b0d 100644 --- a/WebCore/rendering/RenderThemeChromiumLinux.h +++ b/WebCore/rendering/RenderThemeChromiumLinux.h @@ -54,6 +54,13 @@ namespace WebCore { void setCaretBlinkInterval(double interval); virtual double caretBlinkIntervalInternal() const; + static void setScrollbarColors(unsigned inactive_color, + unsigned active_color, + unsigned track_color); + static unsigned thumbInactiveColor() { return m_thumbInactiveColor; } + static unsigned thumbActiveColor() { return m_thumbActiveColor; } + static unsigned trackColor() { return m_trackColor; } + private: RenderThemeChromiumLinux(); virtual ~RenderThemeChromiumLinux(); @@ -62,6 +69,10 @@ namespace WebCore { virtual bool supportsControlTints() const; double m_caretBlinkInterval; + + static unsigned m_thumbInactiveColor; + static unsigned m_thumbActiveColor; + static unsigned m_trackColor; }; } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index bcfcd57..4e57cb5 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -983,7 +983,7 @@ bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderOb paintInfo.context->save(); - paintInfo.context->setFillColor(o->style()->color()); + paintInfo.context->setFillColor(o->style()->color(), DeviceColorSpace); paintInfo.context->setStrokeStyle(NoStroke); FloatPoint arrow1[3]; @@ -1012,11 +1012,11 @@ bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderOb // Draw the separator to the left of the arrows paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin. paintInfo.context->setStrokeStyle(SolidStroke); - paintInfo.context->setStrokeColor(leftSeparatorColor); + paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), IntPoint(leftEdgeOfSeparator, bounds.bottom())); - paintInfo.context->setStrokeColor(rightSeparatorColor); + paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom())); diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index fb42bb7..016a264 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -231,7 +231,7 @@ bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const RenderObject: else image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage; - i.context->drawImage(image, rect); + i.context->drawImage(image, o->style()->colorSpace(), rect); return false; } @@ -263,7 +263,7 @@ bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const RenderObject::Pa else image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage; - i.context->drawImage(image, rect); + i.context->drawImage(image, o->style()->colorSpace(), rect); return false; } @@ -348,6 +348,15 @@ bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const RenderObject::P return false; } +void RenderThemeChromiumSkia::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + if (style->appearance() == PushButtonPart) { + // Ignore line-height. + style->setLineHeight(RenderStyle::initialLineHeight()); + } +} + + bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { return true; @@ -358,6 +367,12 @@ bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const RenderObject: return paintTextField(o, i, r); } +void RenderThemeChromiumSkia::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + // Ignore line-height. + style->setLineHeight(RenderStyle::initialLineHeight()); +} + bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); @@ -393,7 +408,7 @@ bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* o, cons static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef(); static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef(); - i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds); + i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o->style()->colorSpace(), bounds); return false; } @@ -433,7 +448,7 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* o, bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef(); - i.context->drawImage(magnifierImage, bounds); + i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); return false; } @@ -469,7 +484,7 @@ bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, con bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef(); - i.context->drawImage(magnifierImage, bounds); + i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); return false; } diff --git a/WebCore/rendering/RenderThemeChromiumSkia.h b/WebCore/rendering/RenderThemeChromiumSkia.h index 98e3a35..18fa859 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.h +++ b/WebCore/rendering/RenderThemeChromiumSkia.h @@ -71,11 +71,13 @@ namespace WebCore { virtual void setRadioSize(RenderStyle*) const; virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index 1d68c63..48c6c42 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -126,6 +126,7 @@ protected: virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaRewindButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaTimeRemaining(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index 03e39a0..6304947 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -913,7 +913,7 @@ bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::Pa paintInfo.context->save(); - paintInfo.context->setFillColor(o->style()->color()); + paintInfo.context->setFillColor(o->style()->color(), o->style()->colorSpace()); paintInfo.context->setStrokeStyle(NoStroke); FloatPoint arrow1[3]; @@ -942,11 +942,11 @@ bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::Pa // Draw the separator to the left of the arrows paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin. paintInfo.context->setStrokeStyle(SolidStroke); - paintInfo.context->setStrokeColor(leftSeparatorColor); + paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), IntPoint(leftEdgeOfSeparator, bounds.bottom())); - paintInfo.context->setStrokeColor(rightSeparatorColor); + paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom())); @@ -1427,8 +1427,6 @@ typedef enum { static int mediaControllerTheme() { - static const long minimumQuickTimeVersion = 0x07630000; // 7.6.3 - static SInt32 quickTimeVersion = 0; static int controllerTheme = -1; if (controllerTheme != -1) @@ -1436,23 +1434,17 @@ static int mediaControllerTheme() controllerTheme = MediaControllerThemeClassic; - if (!quickTimeVersion) { - OSErr err; - err = Gestalt(gestaltQuickTime, &quickTimeVersion); - if (err != noErr) - return controllerTheme; - } - if (quickTimeVersion < minimumQuickTimeVersion) + if (!wkMediaControllerThemeAvailable(MediaControllerThemeQuickTime)) return controllerTheme; Boolean validKey; - Boolean useQTMediaUI = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey); + Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - if (validKey && !useQTMediaUI) + if (validKey && !useQTMediaUIPref) return controllerTheme; #else - if (!validKey || !useQTMediaUI) + if (!validKey || !useQTMediaUIPref) return controllerTheme; #endif @@ -1652,7 +1644,22 @@ bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const Ren return false; } +bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLInputElement* node = static_cast<HTMLInputElement*>(o->node()); + if (!node) + return false; + + MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(node); + if (!btn) + return false; + LocalCurrentGraphicsContext localContext(paintInfo.context); + wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node)); + + return false; +} + bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { Node* node = o->node(); @@ -1698,12 +1705,16 @@ String RenderThemeMac::extraMediaControlsStyleSheet() return String(); } -bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* e) +bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element) { - if (part == MediaFullscreenButtonPart) - return mediaControllerTheme() == MediaControllerThemeQuickTime; + if (part == MediaToggleClosedCaptionsButtonPart) { + + // We rely on QTKit to render captions so don't enable the button unless it will be able to do so. + if (!element->hasTagName(videoTag)) + return false; + } - return RenderTheme::shouldRenderMediaControlPart(part, e); + return RenderTheme::shouldRenderMediaControlPart(part, element); } #endif // ENABLE(VIDEO) diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp index 2ea3b8b..9e97079 100644 --- a/WebCore/rendering/RenderThemeSafari.cpp +++ b/WebCore/rendering/RenderThemeSafari.cpp @@ -830,8 +830,8 @@ bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject: paintInfo.context->save(); - paintInfo.context->setFillColor(o->style()->color()); - paintInfo.context->setStrokeColor(NoStroke); + paintInfo.context->setFillColor(o->style()->color(), DeviceColorSpace); + paintInfo.context->setStrokeColor(NoStroke, DeviceColorSpace); FloatPoint arrow[3]; arrow[0] = FloatPoint(leftEdge, centerY - arrowHeight / 2.0f); @@ -851,11 +851,11 @@ bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject: // Draw the separator to the left of the arrows paintInfo.context->setStrokeThickness(1.0f); paintInfo.context->setStrokeStyle(SolidStroke); - paintInfo.context->setStrokeColor(leftSeparatorColor); + paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), IntPoint(leftEdgeOfSeparator, bounds.bottom())); - paintInfo.context->setStrokeColor(rightSeparatorColor); + paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace); paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom())); diff --git a/WebCore/rendering/RenderThemeWin.cpp b/WebCore/rendering/RenderThemeWin.cpp index 92bfd03..52afbd6 100644 --- a/WebCore/rendering/RenderThemeWin.cpp +++ b/WebCore/rendering/RenderThemeWin.cpp @@ -819,7 +819,7 @@ bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const RenderO static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef(); static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef(); - paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds); + paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o->style()->colorSpace(), bounds); return false; } @@ -868,7 +868,7 @@ bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const Re bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef(); - paintInfo.context->drawImage(magnifierImage, bounds); + paintInfo.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); return false; } @@ -904,7 +904,7 @@ bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const Render bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef(); - paintInfo.context->drawImage(magnifierImage, bounds); + paintInfo.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); return false; } @@ -955,6 +955,23 @@ Color RenderThemeWin::systemColor(int cssValueId) const } #if ENABLE(VIDEO) + +bool RenderThemeWin::shouldRenderMediaControlPart(ControlPart part, Element* element) +{ + if (part == MediaToggleClosedCaptionsButtonPart) { + // We rely on QuickTime to render captions so only enable the button for a video element. +#if SAFARI_THEME_VERSION >= 4 + if (!element->hasTagName(videoTag)) + return false; +#else + return false; +#endif + } + + return RenderTheme::shouldRenderMediaControlPart(part, element); +} + + bool RenderThemeWin::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r); @@ -989,6 +1006,12 @@ bool RenderThemeWin::paintMediaSliderThumb(RenderObject* o, const RenderObject:: { return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r); } + +bool RenderThemeWin::paintMediaToggleClosedCaptionsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + return RenderMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsButton, o, paintInfo, r); +} + #endif } diff --git a/WebCore/rendering/RenderThemeWin.h b/WebCore/rendering/RenderThemeWin.h index 99c2004..a9fa5e6 100644 --- a/WebCore/rendering/RenderThemeWin.h +++ b/WebCore/rendering/RenderThemeWin.h @@ -125,6 +125,7 @@ public: virtual bool supportsFocusRing(const RenderStyle*) const; #if ENABLE(VIDEO) + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); @@ -132,6 +133,7 @@ public: virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); #endif private: diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index b7ab191..a6f5144 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -36,8 +36,10 @@ #include "HTMLNames.h" #include "InlineTextBox.h" #include "RenderBR.h" +#include "RenderFileUploadControl.h" #include "RenderInline.h" #include "RenderListMarker.h" +#include "RenderPart.h" #include "RenderTableCell.h" #include "RenderView.h" #include "RenderWidget.h" @@ -55,6 +57,10 @@ #include "SVGRenderTreeAsText.h" #endif +#if PLATFORM(QT) +#include <QWidget> +#endif + namespace WebCore { using namespace HTMLNames; @@ -217,6 +223,9 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o) ts << " " << r; if (!(o.isText() && !o.isBR())) { + if (o.isFileUploadControl()) { + ts << " " << quoteAndEscapeNonPrintables(toRenderFileUploadControl(&o)->fileTextValue()); + } if (o.parent() && (o.parent()->style()->color() != o.style()->color())) ts << " [color=" << o.style()->color().name() << "]"; @@ -336,6 +345,24 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o) } } +#if PLATFORM(QT) + // Print attributes of embedded QWidgets. E.g. when the WebCore::Widget + // is invisible the QWidget should be invisible too. + if (o.isRenderPart()) { + const RenderPart* part = toRenderPart(const_cast<RenderObject*>(&o)); + if (part->widget() && part->widget()->platformWidget()) { + QWidget* wid = part->widget()->platformWidget(); + + ts << " [QT: "; + ts << "geometry: {" << wid->geometry() << "} "; + ts << "isHidden: " << wid->isHidden() << " "; + ts << "isSelfVisible: " << part->widget()->isSelfVisible() << " "; + ts << "isParentVisible: " << part->widget()->isParentVisible() << " "; + ts << "mask: {" << wid->mask().boundingRect() << "} ] "; + } + } +#endif + return ts; } @@ -535,8 +562,11 @@ static void writeSelection(TextStream& ts, const RenderObject* o) << "selection end: position " << selection.end().deprecatedEditingOffset() << " of " << nodePosition(selection.end().node()) << "\n"; } -String externalRepresentation(RenderObject* o) +String externalRepresentation(Frame* frame) { + frame->document()->updateLayout(); + + RenderObject* o = frame->contentRenderer(); if (!o) return String(); @@ -544,8 +574,6 @@ String externalRepresentation(RenderObject* o) #if ENABLE(SVG) writeRenderResources(ts, o->document()); #endif - if (o->view()->frameView()) - o->view()->frameView()->layout(); if (o->hasLayer()) { RenderLayer* l = toRenderBox(o)->layer(); writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height())); @@ -554,10 +582,13 @@ String externalRepresentation(RenderObject* o) return ts.release(); } -static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* parent) +static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* parent, bool& isFirstCounter) { for (RenderObject* child = parent->firstChild(); child; child = child->nextSibling()) { if (child->isCounter()) { + if (!isFirstCounter) + stream << " "; + isFirstCounter = false; String str(toRenderText(child)->text()); stream << str; } @@ -570,12 +601,13 @@ String counterValueForElement(Element* element) RefPtr<Element> elementRef(element); element->document()->updateLayout(); TextStream stream; + bool isFirstCounter = true; // The counter renderers should be children of anonymous children // (i.e., :before or :after pseudo-elements). if (RenderObject* renderer = element->renderer()) { for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) { if (child->isAnonymous()) - writeCounterValuesFromChildren(stream, child); + writeCounterValuesFromChildren(stream, child, isFirstCounter); } } return stream.release(); diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index 325f109..b00f7c9 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -29,11 +29,12 @@ namespace WebCore { class Element; +class Frame; class RenderObject; class String; class TextStream; -String externalRepresentation(RenderObject*); +String externalRepresentation(Frame*); void write(TextStream&, const RenderObject&, int indent = 0); // Helper function shared with SVGRenderTreeAsText diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index c4a666f..753afe4 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -210,7 +210,7 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int) if (baseColor.alpha() > 0) { paintInfo.context->save(); paintInfo.context->setCompositeOperation(CompositeCopy); - paintInfo.context->fillRect(paintInfo.rect, baseColor); + paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace()); paintInfo.context->restore(); } else paintInfo.context->clearRect(paintInfo.rect); @@ -338,7 +338,13 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const SelectionMap::iterator end = selectedObjects.end(); for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) { RenderSelectionInfo* info = i->second; - selRect.unite(info->rect()); + // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates. + IntRect currRect = info->rect(); + if (RenderBoxModelObject* repaintContainer = info->repaintContainer()) { + FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect)); + currRect = absQuad.enclosingBoundingBox(); + } + selRect.unite(currRect); delete info; } return selRect; @@ -437,7 +443,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e o = o->nextInPreOrder(); } - m_cachedSelectionBounds = IntRect(); + m_layer->clearBlockSelectionGapsBounds(); // Now that the selection state has been updated for the new objects, walk them again and // put them in the new objects list. @@ -450,9 +456,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb); if (blockInfo) break; - blockInfo = new RenderBlockSelectionInfo(cb); - newSelectedBlocks.set(cb, blockInfo); - m_cachedSelectionBounds.unite(blockInfo->rects()); + newSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb)); cb = cb->containingBlock(); } } @@ -529,7 +533,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e void RenderView::clearSelection() { - repaintViewRectangle(m_cachedSelectionBounds); + m_layer->repaintBlockSelectionGaps(); setSelection(0, -1, 0, -1, RepaintNewMinusOld); } diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index a486b34..37b3f01 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML widget for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * Copyright (C) 2006 Apple Computer, Inc. * @@ -77,9 +75,11 @@ public: bool printing() const; void setPrintImages(bool enable) { m_printImages = enable; } bool printImages() const { return m_printImages; } - void setTruncatedAt(int y) { m_truncatedAt = y; m_bestTruncatedAt = m_truncatorWidth = 0; m_forcedPageBreak = false; } + void setTruncatedAt(int y) { m_truncatedAt = y; m_bestTruncatedAt = m_truncatorWidth = 0; m_minimumColumnHeight = 0; m_forcedPageBreak = false; } void setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak = false); + void setMinimumColumnHeight(int height) { m_minimumColumnHeight = height; } int bestTruncatedAt() const { return m_bestTruncatedAt; } + int minimumColumnHeight() const { return m_minimumColumnHeight; } int truncatedAt() const { return m_truncatedAt; } @@ -196,10 +196,9 @@ protected: RenderWidgetSet m_widgets; private: - IntRect m_cachedSelectionBounds; - int m_bestTruncatedAt; int m_truncatorWidth; + int m_minimumColumnHeight; bool m_forcedPageBreak; LayoutState* m_layoutState; unsigned m_layoutStateDisableCount; diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 5a5c9f1..33f03e2 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -23,8 +23,8 @@ #include "config.h" #include "RenderWidget.h" -#include "AnimationController.h" #include "AXObjectCache.h" +#include "AnimationController.h" #include "GraphicsContext.h" #include "HitTestResult.h" #include "RenderView.h" @@ -40,18 +40,65 @@ static HashMap<const Widget*, RenderWidget*>& widgetRendererMap() return *staticWidgetRendererMap; } +static size_t widgetHierarchyUpdateSuspendCount; + +typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap; + +static WidgetToParentMap& widgetNewParentMap() +{ + DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ()); + return map; +} + +void RenderWidget::suspendWidgetHierarchyUpdates() +{ + widgetHierarchyUpdateSuspendCount++; +} + +void RenderWidget::resumeWidgetHierarchyUpdates() +{ + ASSERT(widgetHierarchyUpdateSuspendCount); + if (widgetHierarchyUpdateSuspendCount == 1) { + WidgetToParentMap map = widgetNewParentMap(); + widgetNewParentMap().clear(); + WidgetToParentMap::iterator end = map.end(); + for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) { + Widget* child = it->first.get(); + ScrollView* currentParent = child->parent(); + FrameView* newParent = it->second; + if (newParent != currentParent) { + if (currentParent) + currentParent->removeChild(child); + if (newParent) + newParent->addChild(child); + } + } + } + widgetHierarchyUpdateSuspendCount--; +} + +static void moveWidgetToParentSoon(Widget* child, FrameView* parent) +{ + if (!widgetHierarchyUpdateSuspendCount) { + if (parent) + parent->addChild(child); + else + child->removeFromParent(); + return; + } + widgetNewParentMap().set(child, parent); +} + RenderWidget::RenderWidget(Node* node) : RenderReplaced(node) , m_widget(0) , m_frameView(node->document()->view()) - , m_refCount(0) -{ - view()->addWidget(this); - // Reference counting is used to prevent the widget from being // destroyed while inside the Widget code, which might not be // able to handle that. - ref(); + , m_refCount(1) +{ + view()->addWidget(this); } void RenderWidget::destroy() @@ -62,14 +109,6 @@ void RenderWidget::destroy() // both RenderBox::destroy() and RenderObject::destroy(). // Fix originally made for <rdar://problem/4228818>. - // <rdar://problem/6937089> suggests that node() can be null by the time we call renderArena() - // in the end of this function. One way this might happen is if this function was invoked twice - // in a row, so bail out and turn a crash into an assertion failure in debug builds and a leak - // in release builds. - ASSERT(node()); - if (!node()) - return; - animation()->cancelAnimations(this); if (RenderView* v = view()) @@ -81,12 +120,8 @@ void RenderWidget::destroy() } remove(); - if (m_widget) { - if (m_frameView) - m_frameView->removeChild(m_widget.get()); - widgetRendererMap().remove(m_widget.get()); - } - + setWidget(0); + // removes from override size map if (hasOverrideSize()) setOverrideSize(-1); @@ -100,14 +135,6 @@ void RenderWidget::destroy() destroyLayer(); } - // <rdar://problem/6937089> suggests that node() can be null here. One way this might happen is - // if this function was re-entered (and therefore the null check at the beginning did not fail), - // so bail out and turn a crash into an assertion failure in debug builds and a leak in release - // builds. - ASSERT(node()); - if (!node()) - return; - // Grab the arena from node()->document()->renderArena() before clearing the node pointer. // Clear the node before deref-ing, as this may be deleted when deref is called. RenderArena* arena = renderArena(); @@ -121,39 +148,43 @@ RenderWidget::~RenderWidget() clearWidget(); } -void RenderWidget::setWidgetGeometry(const IntRect& frame) +bool RenderWidget::setWidgetGeometry(const IntRect& frame) { - if (node() && m_widget->frameRect() != frame) { - RenderWidgetProtector protector(this); - RefPtr<Node> protectedNode(node()); - m_widget->setFrameRect(frame); - } + ASSERT(!widgetHierarchyUpdateSuspendCount); + if (!node() || m_widget->frameRect() == frame) + return false; + + RenderWidgetProtector protector(this); + RefPtr<Node> protectedNode(node()); + m_widget->setFrameRect(frame); + return true; } void RenderWidget::setWidget(PassRefPtr<Widget> widget) { - if (widget != m_widget) { - if (m_widget) { - m_widget->removeFromParent(); - widgetRendererMap().remove(m_widget.get()); - clearWidget(); - } - m_widget = widget; - if (m_widget) { - widgetRendererMap().add(m_widget.get(), this); - // if we've already received a layout, apply the calculated space to the - // widget immediately, but we have to have really been full constructed (with a non-null - // style pointer). - if (style()) { - if (!needsLayout()) - setWidgetGeometry(absoluteContentBox()); - if (style()->visibility() != VISIBLE) - m_widget->hide(); - else - m_widget->show(); - } - m_frameView->addChild(m_widget.get()); + if (widget == m_widget) + return; + + if (m_widget) { + moveWidgetToParentSoon(m_widget.get(), 0); + widgetRendererMap().remove(m_widget.get()); + clearWidget(); + } + m_widget = widget; + if (m_widget) { + widgetRendererMap().add(m_widget.get(), this); + // If we've already received a layout, apply the calculated space to the + // widget immediately, but we have to have really been fully constructed (with a non-null + // style pointer). + if (style()) { + if (!needsLayout()) + setWidgetGeometry(absoluteContentBox()); + if (style()->visibility() != VISIBLE) + m_widget->hide(); + else + m_widget->show(); } + moveWidgetToParentSoon(m_widget.get(), m_frameView); } } @@ -229,11 +260,11 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) // Tell the widget to paint now. This is the only time the widget is allowed // to paint itself. That way it will composite properly with z-indexed layers. if (m_substituteImage) - paintInfo.context->drawImage(m_substituteImage.get(), m_widget->frameRect()); + paintInfo.context->drawImage(m_substituteImage.get(), style()->colorSpace(), m_widget->frameRect()); else m_widget->paint(paintInfo.context, paintInfo.rect); - if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaints()) { + if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaintsIfNotOverlapped()) { ASSERT(!paintInfo.overlapTestRequests->contains(this)); paintInfo.overlapTestRequests->set(this, m_widget->frameRect()); } @@ -245,7 +276,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) // Paint a partially transparent wash over selected widgets. if (isSelected() && !document()->printing()) { // FIXME: selectionRect() is in absolute, not painting coordinates. - paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor()); + paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor(), style()->colorSpace()); } } @@ -274,6 +305,7 @@ void RenderWidget::updateWidgetPosition() int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); +<<<<<<< HEAD:WebCore/rendering/RenderWidget.cpp IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); bool boundsChanged = newBounds != oldBounds; @@ -284,6 +316,10 @@ void RenderWidget::updateWidgetPosition() } #ifndef FLATTEN_IFRAME +======= + bool boundsChanged = setWidgetGeometry(IntRect(absPos.x(), absPos.y(), w, h)); + +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderWidget.cpp // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget->isFrameView()) { diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h index 78537fd..6cad04a 100644 --- a/WebCore/rendering/RenderWidget.h +++ b/WebCore/rendering/RenderWidget.h @@ -42,6 +42,9 @@ public: void showSubstituteImage(PassRefPtr<Image>); + static void suspendWidgetHierarchyUpdates(); + static void resumeWidgetHierarchyUpdates(); + protected: RenderWidget(Node*); @@ -61,7 +64,7 @@ private: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); virtual void setOverlapTestResult(bool); - void setWidgetGeometry(const IntRect&); + bool setWidgetGeometry(const IntRect&); friend class RenderWidgetProtector; RenderArena* ref() { ++m_refCount; return renderArena(); } diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index b0b0e15..7fce1d3 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -1,6 +1,4 @@ /* - * This file is part of the line box implementation for KDE. - * * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index d0fa9ae..cf8464e 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -1,6 +1,4 @@ /** - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2007 Rob Buis <buis@kde.org> * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * @@ -384,7 +382,8 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t bool setShadow = false; if (styleToUse->textShadow()) { paintInfo.context->setShadow(IntSize(styleToUse->textShadow()->x, styleToUse->textShadow()->y), - styleToUse->textShadow()->blur, styleToUse->textShadow()->color); + styleToUse->textShadow()->blur, styleToUse->textShadow()->color, + styleToUse->colorSpace()); setShadow = true; } @@ -477,7 +476,7 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar int adjust = startPos >= boxStartOffset ? boxStartOffset : 0; p->drawHighlightForText(font, svgTextRunForInlineTextBox(textRenderer()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x), IntPoint((int) svgChar.x, (int) svgChar.y - font.ascent()), - font.ascent() + font.descent(), color, startPos - adjust, endPos - adjust); + font.ascent() + font.descent(), color, style->colorSpace(), startPos - adjust, endPos - adjust); p->restore(); } diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h index 76837cc..ad39aab 100644 --- a/WebCore/rendering/SVGInlineTextBox.h +++ b/WebCore/rendering/SVGInlineTextBox.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2007 Rob Buis <buis@kde.org> * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index ea087f9..a594410 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -94,8 +94,17 @@ void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject paintInfo.context->beginTransparencyLayer(opacity); } - if (ShadowData* shadow = svgStyle->shadow()) - paintInfo.context->setShadow(IntSize(shadow->x, shadow->y), shadow->blur, shadow->color); + if (ShadowData* shadow = svgStyle->shadow()) { + int xShift = shadow->x < 0 ? shadow->x : 0; + int yShift = shadow->y < 0 ? shadow->y :0; + int widthShift = shadow->x < 0 ? 0 : shadow->x; + int heightShift = shadow->y < 0 ? 0 : shadow->y; + FloatRect shadowRect = FloatRect(boundingBox.x() + xShift, boundingBox.y() + yShift, + boundingBox.width() + widthShift, boundingBox.height() + heightShift); + paintInfo.context->clip(enclosingIntRect(shadowRect)); + 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()); @@ -163,6 +172,11 @@ void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::P float opacity = style->opacity(); if (opacity < 1.0f) paintInfo.context->endTransparencyLayer(); + + // This needs to be done separately from opacity, because if both properties are set, + // then the transparency layers are nested. + if (style->svgStyle()->shadow()) + paintInfo.context->endTransparencyLayer(); } void renderSubtreeToImage(ImageBuffer* image, RenderObject* item) diff --git a/WebCore/rendering/TableLayout.h b/WebCore/rendering/TableLayout.h index 8ae0ce7..10d6e26 100644 --- a/WebCore/rendering/TableLayout.h +++ b/WebCore/rendering/TableLayout.h @@ -1,6 +1,4 @@ /* - * This file is part of the HTML rendering engine for KDE. - * * Copyright (C) 2002 Lars Knoll (knoll@kde.org) * (C) 2002 Dirk Mueller (mueller@kde.org) * @@ -23,11 +21,13 @@ #ifndef TableLayout_h #define TableLayout_h +#include <wtf/Noncopyable.h> + namespace WebCore { class RenderTable; -class TableLayout { +class TableLayout : public Noncopyable { public: TableLayout(RenderTable* table) : m_table(table) diff --git a/WebCore/rendering/break_lines.h b/WebCore/rendering/break_lines.h index 14f740f..4d6b8dc 100644 --- a/WebCore/rendering/break_lines.h +++ b/WebCore/rendering/break_lines.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or diff --git a/WebCore/rendering/style/ContentData.h b/WebCore/rendering/style/ContentData.h index 24d5f86..2c261f8 100644 --- a/WebCore/rendering/style/ContentData.h +++ b/WebCore/rendering/style/ContentData.h @@ -25,15 +25,15 @@ #ifndef ContentData_h #define ContentData_h -#include "PlatformString.h" #include "RenderStyleConstants.h" -#include "StringImpl.h" -#include "StyleImage.h" #include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> namespace WebCore { class CounterContent; +class StringImpl; +class StyleImage; struct ContentData : Noncopyable { public: diff --git a/WebCore/rendering/style/CounterContent.h b/WebCore/rendering/style/CounterContent.h index cf11813..702d9c2 100644 --- a/WebCore/rendering/style/CounterContent.h +++ b/WebCore/rendering/style/CounterContent.h @@ -30,7 +30,7 @@ namespace WebCore { -class CounterContent { +class CounterContent : public FastAllocBase { public: CounterContent(const AtomicString& identifier, EListStyleType style, const AtomicString& separator) : m_identifier(identifier) diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h index fb928b6..9c615b4 100644 --- a/WebCore/rendering/style/FillLayer.h +++ b/WebCore/rendering/style/FillLayer.h @@ -59,7 +59,7 @@ struct FillSize { LengthSize size; }; -struct FillLayer { +struct FillLayer : FastAllocBase { public: FillLayer(EFillLayerType); ~FillLayer(); diff --git a/WebCore/rendering/style/LineClampValue.h b/WebCore/rendering/style/LineClampValue.h new file mode 100644 index 0000000..2119ca2 --- /dev/null +++ b/WebCore/rendering/style/LineClampValue.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LineClampValue_h +#define LineClampValue_h + +#include "RenderStyleConstants.h" + +namespace WebCore { + +class LineClampValue { +public: + LineClampValue() + : m_type(LineClampLineCount) + , m_value(-1) + { + } + + LineClampValue(int value, ELineClampType type) + : m_type(type) + , m_value(value) + { + } + + int value() const { return m_value; } + + bool isPercentage() const { return m_type == LineClampPercentage; } + + bool isNone() const { return m_value == -1; } + + bool operator==(const LineClampValue& o) const + { + return value() == o.value() && isPercentage() == o.isPercentage(); + } + + bool operator!=(const LineClampValue& o) const + { + return !(*this == o); + } + +private: + ELineClampType m_type; + int m_value; +}; + +} // namespace WebCore + +#endif // LineClampValue_h diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index a861fea..59d40b4 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -454,8 +454,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom) return StyleDifferenceLayout; - if (rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1 || - rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1) { + if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) || + (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) { // FIXME: We should add an optimized form of layout that just recomputes visual overflow. return StyleDifferenceLayout; } diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 674f062..a72b66d 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -37,6 +37,7 @@ #include "CachedImage.h" #include "CollapsedBorderValue.h" #include "Color.h" +#include "ColorSpace.h" #include "ContentData.h" #include "CounterDirectives.h" #include "CursorList.h" @@ -49,6 +50,7 @@ #include "Length.h" #include "LengthBox.h" #include "LengthSize.h" +#include "LineClampValue.h" #include "NinePieceImage.h" #include "OutlineValue.h" #include "Pair.h" @@ -599,6 +601,7 @@ public: const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; } const Color& textFillColor() const { return rareInheritedData->textFillColor; } + ColorSpace colorSpace() const { return static_cast<ColorSpace>(rareInheritedData->colorSpace); } float opacity() const { return rareNonInheritedData->opacity; } ControlPart appearance() const { return static_cast<ControlPart>(rareNonInheritedData->m_appearance); } EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->align); } @@ -693,7 +696,7 @@ public: bool isRunningAcceleratedAnimation() const { return rareNonInheritedData->m_runningAcceleratedAnimation; } #endif - int lineClamp() const { return rareNonInheritedData->lineClamp; } + const LineClampValue& lineClamp() const { return rareNonInheritedData->lineClamp; } bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; } ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); } @@ -934,6 +937,7 @@ public: void setTextStrokeColor(const Color& c) { SET_VAR(rareInheritedData, textStrokeColor, c) } void setTextStrokeWidth(float w) { SET_VAR(rareInheritedData, textStrokeWidth, w) } void setTextFillColor(const Color& c) { SET_VAR(rareInheritedData, textFillColor, c) } + void setColorSpace(ColorSpace space) { SET_VAR(rareInheritedData, colorSpace, space) } void setOpacity(float f) { SET_VAR(rareNonInheritedData, opacity, f); } void setAppearance(ControlPart a) { SET_VAR(rareNonInheritedData, m_appearance, a); } void setBoxAlign(EBoxAlignment a) { SET_VAR(rareNonInheritedData.access()->flexibleBox, align, a); } @@ -1013,7 +1017,7 @@ public: void setIsRunningAcceleratedAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_runningAcceleratedAnimation, b); } #endif - void setLineClamp(int c) { SET_VAR(rareNonInheritedData, lineClamp, c); } + void setLineClamp(LineClampValue c) { SET_VAR(rareNonInheritedData, lineClamp, c); } void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); } void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); } @@ -1186,9 +1190,10 @@ public: static float initialPerspective() { return 0; } static Length initialPerspectiveOriginX() { return Length(50.0, Percent); } static Length initialPerspectiveOriginY() { return Length(50.0, Percent); } + static Color initialBackgroundColor() { return Color::transparent; } // Keep these at the end. - static int initialLineClamp() { return -1; } + static LineClampValue initialLineClamp() { return LineClampValue(); } static bool initialTextSizeAdjust() { return true; } static ETextSecurity initialTextSecurity() { return TSNONE; } #if ENABLE(DASHBOARD_SUPPORT) diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index 3010947..92cd3d5 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -2,7 +2,7 @@ * Copyright (C) 2000 Lars Knoll (knoll@kde.org) * (C) 2000 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * @@ -69,8 +69,9 @@ enum PseudoId { NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER, SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL, MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER, - MEDIA_CONTROLS_VOLUME_SLIDER, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, 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_VOLUME_SLIDER, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, + 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, @@ -321,6 +322,8 @@ enum ETransformStyle3D { enum EBackfaceVisibility { BackfaceVisibilityVisible, BackfaceVisibilityHidden }; + +enum ELineClampType { LineClampLineCount, LineClampPercentage }; } // namespace WebCore diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index e8827c4..728738b 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -8,8 +8,6 @@ Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org) Copyright (C) 2002 Apple Computer, Inc. - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index 12477d7..c65be97 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -3,8 +3,6 @@ 2004, 2005 Rob Buis <buis@kde.org> Copyright (C) 2005, 2006 Apple Computer, Inc. - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.cpp b/WebCore/rendering/style/SVGRenderStyleDefs.cpp index 2ed1d8f..093f1f1 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.cpp +++ b/WebCore/rendering/style/SVGRenderStyleDefs.cpp @@ -8,8 +8,6 @@ Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org) Copyright (C) 2002 Apple Computer, Inc. - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h index f4cf932..8f01d9f 100644 --- a/WebCore/rendering/style/SVGRenderStyleDefs.h +++ b/WebCore/rendering/style/SVGRenderStyleDefs.h @@ -8,8 +8,6 @@ (C) 2000-2003 Dirk Mueller (mueller@kde.org) (C) 2002-2003 Apple Computer, Inc. - This file is part of the KDE project - 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 diff --git a/WebCore/rendering/style/ShadowData.h b/WebCore/rendering/style/ShadowData.h index f4061f2..089cf77 100644 --- a/WebCore/rendering/style/ShadowData.h +++ b/WebCore/rendering/style/ShadowData.h @@ -26,6 +26,7 @@ #define ShadowData_h #include "Color.h" +#include <wtf/FastAllocBase.h> namespace WebCore { @@ -33,7 +34,7 @@ enum ShadowStyle { Normal, Inset }; // This struct holds information about shadows for the text-shadow and box-shadow properties. -struct ShadowData { +struct ShadowData : FastAllocBase { ShadowData() : x(0) , y(0) diff --git a/WebCore/rendering/style/StyleBackgroundData.cpp b/WebCore/rendering/style/StyleBackgroundData.cpp index 68a9ddd..08f5527 100644 --- a/WebCore/rendering/style/StyleBackgroundData.cpp +++ b/WebCore/rendering/style/StyleBackgroundData.cpp @@ -22,12 +22,14 @@ #include "config.h" #include "StyleBackgroundData.h" +#include "RenderStyle.h" #include "RenderStyleConstants.h" namespace WebCore { StyleBackgroundData::StyleBackgroundData() : m_background(BackgroundFillLayer) + , m_color(RenderStyle::initialBackgroundColor()) { } diff --git a/WebCore/rendering/style/StyleRareInheritedData.cpp b/WebCore/rendering/style/StyleRareInheritedData.cpp index 0f3b7e7..ff626b7 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -42,6 +42,7 @@ StyleRareInheritedData::StyleRareInheritedData() , textSizeAdjust(RenderStyle::initialTextSizeAdjust()) , resize(RenderStyle::initialResize()) , userSelect(RenderStyle::initialUserSelect()) + , colorSpace(DeviceColorSpace) { } @@ -64,6 +65,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , textSizeAdjust(o.textSizeAdjust) , resize(o.resize) , userSelect(o.userSelect) + , colorSpace(o.colorSpace) { } @@ -90,7 +92,8 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && tapHighlightColor == o.tapHighlightColor #endif && resize == o.resize - && userSelect == o.userSelect; + && userSelect == o.userSelect + && colorSpace == o.colorSpace; } bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h index 4abd3cf..1aa7b05 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.h +++ b/WebCore/rendering/style/StyleRareInheritedData.h @@ -68,6 +68,7 @@ public: bool textSizeAdjust : 1; // An Apple extension. unsigned resize : 2; // EResize unsigned userSelect : 1; // EUserSelect + unsigned colorSpace : 1; // ColorSpace private: StyleRareInheritedData(); diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h index 8dd22b3..452b273 100644 --- a/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -29,6 +29,7 @@ #include "CursorData.h" #include "DataRef.h" #include "FillLayer.h" +#include "LineClampValue.h" #include "NinePieceImage.h" #include "StyleTransformData.h" #include <wtf/OwnPtr.h> @@ -77,7 +78,7 @@ public: bool animationDataEquivalent(const StyleRareNonInheritedData&) const; bool transitionDataEquivalent(const StyleRareNonInheritedData&) const; - int lineClamp; // An Apple extension. + LineClampValue lineClamp; // An Apple extension. #if ENABLE(DASHBOARD_SUPPORT) Vector<StyleDashboardRegion> m_dashboardRegions; #endif |