diff options
Diffstat (limited to 'WebCore/rendering')
48 files changed, 627 insertions, 610 deletions
diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index dd96e0e..496c4ba 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -166,7 +166,7 @@ String HitTestResult::spellingToolTip(TextDirection& dir) const if (!m_innerNonSharedNode) return String(); - DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar); + DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(m_point, DocumentMarker::Grammar); if (!marker) return String(); @@ -182,7 +182,7 @@ String HitTestResult::replacedString() const if (!m_innerNonSharedNode) return String(); - DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Replacement); + DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(m_point, DocumentMarker::Replacement); if (!marker) return String(); diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 50f6cfa..cb4fdb8 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -810,7 +810,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in if (grammar) { markerRect.move(-tx, -ty); markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); - renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); + renderer()->document()->markers()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); } } @@ -848,7 +848,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, co // 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 = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); - renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); + renderer()->document()->markers()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); // Optionally highlight the text if (renderer()->frame()->markedTextMatchesAreHighlighted()) { @@ -877,7 +877,7 @@ void InlineTextBox::computeRectForReplacementMarker(int /*tx*/, int /*ty*/, cons // Compute and store the rect associated with this marker. IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos)); markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); - renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); + renderer()->document()->markers()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); } void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, RenderStyle* style, const Font& font, bool background) @@ -885,7 +885,7 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re if (!renderer()->node()) return; - Vector<DocumentMarker> markers = renderer()->document()->markersForNode(renderer()->node()); + Vector<DocumentMarker> markers = renderer()->document()->markers()->markersForNode(renderer()->node()); Vector<DocumentMarker>::iterator markerIt = markers.begin(); // Give any document markers that touch this run a chance to draw before the text has been drawn. diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index d4eb9a9..3fb712f 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -135,7 +135,9 @@ PassRefPtr<MediaControlElement> MediaControlElement::create(HTMLMediaElement* me void MediaControlElement::attachToParent(Element* parent) { - parent->legacyParserAddChild(this); + // FIXME: This code seems very wrong. Why are we magically adding |this| to the DOM here? + // We shouldn't be calling parser API methods outside of the parser! + parent->parserAddChild(this); } void MediaControlElement::update() @@ -392,7 +394,9 @@ MediaControlInputElement::MediaControlInputElement(HTMLMediaElement* mediaElemen void MediaControlInputElement::attachToParent(Element* parent) { - parent->legacyParserAddChild(this); + // FIXME: This code seems very wrong. Why are we magically adding |this| to the DOM here? + // We shouldn't be calling parser API methods outside of the parser! + parent->parserAddChild(this); } void MediaControlInputElement::update() diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h index ceb0255..1dcf6be 100644 --- a/WebCore/rendering/MediaControlElements.h +++ b/WebCore/rendering/MediaControlElements.h @@ -81,7 +81,7 @@ private: MediaControlShadowRootElement(HTMLMediaElement*); virtual bool isShadowNode() const { return true; } - virtual Node* shadowParentNode() { return m_mediaElement; } + virtual ContainerNode* shadowParentNode() { return m_mediaElement; } HTMLMediaElement* m_mediaElement; }; diff --git a/WebCore/rendering/PaintInfo.h b/WebCore/rendering/PaintInfo.h index 213eb30..3598807 100644 --- a/WebCore/rendering/PaintInfo.h +++ b/WebCore/rendering/PaintInfo.h @@ -86,10 +86,16 @@ struct PaintInfo { return; context->concatCTM(localToAncestorTransform); + + if (rect == infiniteRect()) + return; + rect = localToAncestorTransform.inverse().mapRect(rect); } #endif + static IntRect infiniteRect() { return IntRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX); } + // FIXME: Introduce setters/getters at some point. Requires a lot of changes throughout rendering/. GraphicsContext* context; IntRect rect; diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 02b0079..28d7914 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1265,8 +1265,8 @@ void RenderBlock::layoutBlock(bool relayoutChildren) int repaintRight = max(rightVisualOverflow(), rightLayoutOverflow()); IntRect repaintRect(repaintLeft, repaintTop, repaintRight - repaintLeft, repaintBottom - repaintTop); - // FIXME: Deal with multiple column repainting. We have to split the repaint - // rect up into multiple rects if it spans columns. + // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union. + adjustRectForColumns(repaintRect); repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline)); diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp index 3cb9a07..6e678e8 100644 --- a/WebCore/rendering/RenderCounter.cpp +++ b/WebCore/rendering/RenderCounter.cpp @@ -136,6 +136,11 @@ static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& RenderObject* currentRenderer = counterOwner->previousInPreOrder(); previousSibling = 0; while (currentRenderer) { + // A sibling without a parent means that the counter node tree was not constructed correctly so we stop + // traversing. In the future RenderCounter should handle RenderObjects that are not connected to the + // render tree at counter node creation. See bug 43812. + if (previousSibling && !previousSibling->parent()) + return false; CounterNode* currentCounter = makeCounterNode(currentRenderer, identifier, false); if (searchEndRenderer == currentRenderer) { // We may be at the end of our search. diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index df80a7c..347fa32 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -1359,7 +1359,7 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai Frame* frame = renderer()->frame(); if (frame) { // The caret rect needs to be invalidated after scrolling - frame->selection()->setNeedsLayout(); + frame->selection()->setCaretRectNeedsUpdate(); FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint); if (repaintContainer) @@ -3128,7 +3128,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl { if (!parent()) { // The root layer's clip rect is always infinite. - clipRects.reset(ClipRects::infiniteRect()); + clipRects.reset(PaintInfo::infiniteRect()); return; } @@ -3144,7 +3144,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl parentLayer->calculateClipRects(rootLayer, clipRects); } else - clipRects.reset(ClipRects::infiniteRect()); + clipRects.reset(PaintInfo::infiniteRect()); // A fixed object is essentially the root of its containing block hierarchy, so when // we encounter such an object, we reset our clip rects to the fixedClipRect. diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index ba79292..17521ad 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -145,8 +145,6 @@ public: m_fixed = other.fixed(); return *this; } - - static IntRect infiniteRect() { return IntRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); } private: // The normal operator new is disallowed on all render objects. diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 0db94dc..23645d5 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -276,7 +276,7 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() static IntRect clipBox(RenderBox* renderer) { - IntRect result = ClipRects::infiniteRect(); + IntRect result = PaintInfo::infiniteRect(); if (renderer->hasOverflowClip()) result = renderer->overflowClipRect(0, 0); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index 72a2d32..d125a24 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -97,6 +97,7 @@ struct CompositingState { RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) : m_renderView(renderView) , m_rootPlatformLayer(0) + , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired) , m_hasAcceleratedCompositing(true) , m_showDebugBorders(false) , m_showRepaintCounter(false) @@ -174,8 +175,26 @@ void RenderLayerCompositor::scheduleSync() page->chrome()->client()->scheduleCompositingLayerSync(); } +void RenderLayerCompositor::scheduleCompositingLayerUpdate() +{ + if (!m_updateCompositingLayersTimer.isActive()) + m_updateCompositingLayersTimer.startOneShot(0); +} + +bool RenderLayerCompositor::compositingLayerUpdatePending() const +{ + return m_updateCompositingLayersTimer.isActive(); +} + +void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*) +{ + updateCompositingLayers(); +} + void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot) { + m_updateCompositingLayersTimer.stop(); + if (!m_compositingDependsOnGeometry && !m_compositing) return; @@ -1225,7 +1244,7 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const return false; IntRect backgroundRect = layer->backgroundClipRect(computeClipRoot, true); - return backgroundRect != ClipRects::infiniteRect(); + return backgroundRect != PaintInfo::infiniteRect(); } // Return true if the given layer is a stacking context and has compositing child @@ -1483,7 +1502,7 @@ void RenderLayerCompositor::detachRootPlatformLayer() else m_rootPlatformLayer->removeFromParent(); - if (Element* ownerElement = m_renderView->document()->ownerElement()) + if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement()) scheduleNeedsStyleRecalc(ownerElement); break; } @@ -1544,6 +1563,11 @@ void RenderLayerCompositor::notifyIFramesOfCompositingChange() if (child->document() && child->document()->ownerElement()) scheduleNeedsStyleRecalc(child->document()->ownerElement()); } + + // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so + // we need to schedule a style recalc in our parent document. + if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement()) + scheduleNeedsStyleRecalc(ownerElement); } bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index 67623d4..917d610 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -88,7 +88,11 @@ public: // Rebuild the tree of compositing layers void updateCompositingLayers(CompositingUpdateType = CompositingUpdateAfterLayoutOrStyleChange, RenderLayer* updateRoot = 0); - + // This is only used when state changes and we do not exepect a style update or layout to happen soon (e.g. when + // we discover that an iframe is overlapped during painting). + void scheduleCompositingLayerUpdate(); + bool compositingLayerUpdatePending() const; + // Update the compositing state of the given layer. Returns true if that state changed. enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater }; bool updateLayerCompositingState(RenderLayer*, CompositingChangeRepaint = CompositingChangeRepaintNow); @@ -179,6 +183,8 @@ private: static void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed); static bool overlapsCompositedLayers(OverlapMap&, const IntRect& layerBounds); + void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*); + // Returns true if any layer's compositing changed void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged); @@ -224,6 +230,8 @@ private: private: RenderView* m_renderView; OwnPtr<GraphicsLayer> m_rootPlatformLayer; + Timer<RenderLayerCompositor> m_updateCompositingLayersTimer; + bool m_hasAcceleratedCompositing; bool m_showDebugBorders; bool m_showRepaintCounter; diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index e148c81..6ff1709 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -48,8 +48,7 @@ static String toRoman(int number, bool upper) // FIXME: CSS3 describes how to make this work for much larger numbers, // using overbars and special characters. It also specifies the characters // in the range U+2160 to U+217F instead of standard ASCII ones. - if (number < 1 || number > 3999) - return String::number(number); + ASSERT(number >= 1 && number <= 3999); // Big enough to store largest roman number less than 3999 which // is 3888 (MMMDCCCLXXXVIII) @@ -118,9 +117,6 @@ static inline String toAlphabeticOrNumeric(int number, const UChar* sequence, in static String toAlphabetic(int number, const UChar* alphabet, int alphabetSize) { - if (number < 1) - return String::number(number); - return toAlphabeticOrNumeric(number, alphabet, alphabetSize, AlphabeticSequence); } @@ -170,8 +166,7 @@ static int toHebrewUnder1000(int number, UChar letters[5]) static String toHebrew(int number) { // FIXME: CSS3 mentions ways to make this work for much larger numbers. - if (number < 0 || number > 999999) - return String::number(number); + ASSERT(number >= 0 && number <= 999999); if (number == 0) { static const UChar hebrewZero[3] = { 0x05D0, 0x05E4, 0x05E1 }; @@ -238,8 +233,7 @@ static int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UCha static String toArmenian(int number, bool upper) { - if (number < 1 || number > 99999999) - return String::number(number); + ASSERT(number >= 1 && number <= 99999999); const int lettersSize = 18; // twice what toArmenianUnder10000 needs UChar letters[lettersSize]; @@ -253,8 +247,7 @@ static String toArmenian(int number, bool upper) static String toGeorgian(int number) { - if (number < 1 || number > 19999) - return String::number(number); + ASSERT(number >= 1 && number <= 19999); const int lettersSize = 5; UChar letters[lettersSize]; @@ -300,8 +293,7 @@ static String toGeorgian(int number) // first 3 group markers, then 3 digit markers, then ten digits. static String toCJKIdeographic(int number, const UChar table[16]) { - if (number < 0) - return String::number(number); + ASSERT(number >= 0); enum AbstractCJKChar { noChar, @@ -379,11 +371,110 @@ static String toCJKIdeographic(int number, const UChar table[16]) return String(characters, length); } -static UChar listMarkerSuffix(EListStyleType type) +static EListStyleType effectiveListMarkerType(EListStyleType type, int value) +{ + // Note, the following switch statement has been explicitly grouped + // by list-style-type ordinal range. + switch (type) { + case ArabicIndic: + case Bengali: + case BinaryListStyle: + case Cambodian: + case Circle: + case DecimalLeadingZero: + case DecimalListStyle: + case Devanagari: + case Disc: + case Gujarati: + case Gurmukhi: + case Kannada: + case Khmer: + case Lao: + case LowerHexadecimal: + case Malayalam: + case Mongolian: + case Myanmar: + case NoneListStyle: + case Octal: + case Oriya: + case Persian: + case Square: + case Telugu: + case Thai: + case Tibetan: + case UpperHexadecimal: + case Urdu: + return type; // Can represent all ordinals. + case Armenian: + return (value < 1 || value > 99999999) ? DecimalListStyle : type; + case CJKIdeographic: + return (value < 0) ? DecimalListStyle : type; + case Georgian: + return (value < 1 || value > 19999) ? DecimalListStyle : type; + case Hebrew: + return (value < 0 || value > 999999) ? DecimalListStyle : type; + case LowerRoman: + case UpperRoman: + return (value < 1 || value > 3999) ? DecimalListStyle : type; + case Afar: + case Amharic: + case AmharicAbegede: + case CjkEarthlyBranch: + case CjkHeavenlyStem: + case Ethiopic: + case EthiopicAbegede: + case EthiopicAbegedeAmEt: + case EthiopicAbegedeGez: + case EthiopicAbegedeTiEr: + case EthiopicAbegedeTiEt: + case EthiopicHalehameAaEr: + case EthiopicHalehameAaEt: + case EthiopicHalehameAmEt: + case EthiopicHalehameGez: + case EthiopicHalehameOmEt: + case EthiopicHalehameSidEt: + case EthiopicHalehameSoEt: + case EthiopicHalehameTiEr: + case EthiopicHalehameTiEt: + case EthiopicHalehameTig: + case Hangul: + case HangulConsonant: + case Hiragana: + case HiraganaIroha: + case Katakana: + case KatakanaIroha: + case LowerAlpha: + case LowerGreek: + case LowerLatin: + case LowerNorwegian: + case Oromo: + case Sidama: + case Somali: + case Tigre: + case TigrinyaEr: + case TigrinyaErAbegede: + case TigrinyaEt: + case TigrinyaEtAbegede: + case UpperAlpha: + case UpperGreek: + case UpperLatin: + case UpperNorwegian: + return (value < 1) ? DecimalListStyle : type; + } + + ASSERT_NOT_REACHED(); + return type; +} + +static UChar listMarkerSuffix(EListStyleType type, int value) { + // If the list-style-type cannot represent |value| because it's outside its + // ordinal range then we fall back to some list style that can represent |value|. + EListStyleType effectiveType = effectiveListMarkerType(type, value); + // Note, the following switch statement has been explicitly // grouped by list-style-type suffix. - switch (type) { + switch (effectiveType) { case NoneListStyle: case Disc: case Circle: @@ -473,7 +564,9 @@ static UChar listMarkerSuffix(EListStyleType type) String listMarkerText(EListStyleType type, int value) { - switch (type) { + // If the list-style-type, say hebrew, cannot represent |value| because it's outside + // its ordinal range then we fallback to some list style that can represent |value|. + switch (effectiveListMarkerType(type, value)) { case NoneListStyle: return ""; @@ -1122,7 +1215,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) } const Font& font = style()->font(); - const UChar suffix = listMarkerSuffix(type); + const UChar suffix = listMarkerSuffix(type, m_listItem->value()); if (style()->direction() == LTR) { int width = font.width(textRun); context->drawText(style()->font(), textRun, marker.location()); @@ -1282,7 +1375,7 @@ void RenderListMarker::calcPrefWidths() width = 0; else { int itemWidth = font.width(m_text); - UChar suffixSpace[2] = { listMarkerSuffix(type), ' ' }; + UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' }; int suffixSpaceWidth = font.width(TextRun(suffixSpace, 2)); width = itemWidth + suffixSpaceWidth; } @@ -1484,7 +1577,7 @@ IntRect RenderListMarker::getRelativeMarkerRect() return IntRect(); const Font& font = style()->font(); int itemWidth = font.width(m_text); - UChar suffixSpace[2] = { listMarkerSuffix(type), ' ' }; + UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' }; int suffixSpaceWidth = font.width(TextRun(suffixSpace, 2)); return IntRect(x(), y() + font.ascent(), itemWidth + suffixSpaceWidth, font.height()); } diff --git a/WebCore/rendering/RenderMeter.cpp b/WebCore/rendering/RenderMeter.cpp index cfa7cba..1a99976 100644 --- a/WebCore/rendering/RenderMeter.cpp +++ b/WebCore/rendering/RenderMeter.cpp @@ -162,9 +162,9 @@ void RenderMeter::updatePartsState() { if (shouldHaveParts() && !m_barPart) { ASSERT(!m_valuePart); - m_barPart = ShadowBlockElement::createForPart(this->node(), barPseudoId()); + m_barPart = ShadowBlockElement::createForPart(static_cast<HTMLElement*>(node()), barPseudoId()); addChild(m_barPart->renderer()); - m_valuePart = ShadowBlockElement::createForPart(this->node(), valuePseudoId()); + m_valuePart = ShadowBlockElement::createForPart(static_cast<HTMLElement*>(node()), valuePseudoId()); addChild(m_valuePart->renderer()); } else if (!shouldHaveParts() && m_barPart) { ASSERT(m_valuePart); diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 783ed63..78da758 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -1594,7 +1594,10 @@ Color RenderObject::selectionBackgroundColor() const Color RenderObject::selectionForegroundColor() const { Color color; - if (style()->userSelect() == SELECT_NONE) + // If the element is unselectable, or we are only painting the selection, + // don't override the foreground color with the selection foreground color. + if (style()->userSelect() == SELECT_NONE + || (frame()->view()->paintBehavior() & PaintBehaviorSelectionOnly)) return color; if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION)) { diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index ddc2c45..86a12c8 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -127,33 +127,43 @@ void RenderPath::layout() setNeedsLayout(false); } -static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderPath* object) +void RenderPath::fillAndStrokePath(GraphicsContext* context) { context->beginPath(); - RenderStyle* style = object->style(); + RenderStyle* style = this->style(); - if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(object, style)) { - context->addPath(path); - if (fillPaintingResource->applyResource(object, style, context, ApplyToFillMode)) - fillPaintingResource->postApplyResource(object, context, ApplyToFillMode); + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style)) { + context->addPath(m_path); + if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) + fillPaintingResource->postApplyResource(this, context, ApplyToFillMode); } - if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(object, style)) { - if (style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) { - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); - AffineTransform transform = element->getScreenCTM(); - if (!transform.isInvertible()) - return; - - Path transformedPath = path; - context->concatCTM(transform.inverse()); - transformedPath.transform(transform); - context->addPath(transformedPath); - } else - context->addPath(path); - if (strokePaintingResource->applyResource(object, style, context, ApplyToStrokeMode)) - strokePaintingResource->postApplyResource(object, context, ApplyToStrokeMode); - } + RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style); + if (!strokePaintingResource) + return; + + bool restoreContext = false; + if (style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) { + SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate); + if (!nonScalingStrokeTransform.isInvertible()) + return; + + Path transformedPath = m_path; + transformedPath.transform(nonScalingStrokeTransform); + + context->save(); + context->concatCTM(nonScalingStrokeTransform.inverse()); + context->addPath(transformedPath); + restoreContext = true; + } else + context->addPath(m_path); + + if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode)) + strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode); + + if (restoreContext) + context->restore(); } void RenderPath::paint(PaintInfo& paintInfo, int, int) @@ -180,7 +190,7 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int) if (svgStyle->shapeRendering() == SR_CRISPEDGES) childPaintInfo.context->setShouldAntialias(false); - fillAndStrokePath(m_path, childPaintInfo.context, this); + fillAndStrokePath(childPaintInfo.context); if (svgStyle->hasMarkers()) m_markerLayoutInfo.drawMarkers(childPaintInfo); diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index 57900ad..1bdac07 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -70,6 +70,7 @@ private: private: virtual AffineTransform localTransform() const { return m_localTransform; } + void fillAndStrokePath(GraphicsContext*); bool m_needsBoundariesUpdate : 1; bool m_needsPathUpdate : 1; diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp index 6072e1e..d6e2dc7 100644 --- a/WebCore/rendering/RenderProgress.cpp +++ b/WebCore/rendering/RenderProgress.cpp @@ -109,7 +109,7 @@ void RenderProgress::updatePartsState() { if (shouldHaveParts() && !m_valuePart) { style()->setAppearance(NoControlPart); - m_valuePart = ShadowBlockElement::createForPart(this->node(), PROGRESS_BAR_VALUE); + m_valuePart = ShadowBlockElement::createForPart(static_cast<HTMLElement*>(node()), PROGRESS_BAR_VALUE); addChild(m_valuePart->renderer()); } else if (!shouldHaveParts() && m_valuePart) { m_valuePart->detach(); diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index 626a880..ef44a79 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -37,6 +37,7 @@ #include "RenderStyle.h" #include "SVGClipPathElement.h" #include "SVGElement.h" +#include "SVGImageBufferTools.h" #include "SVGRenderSupport.h" #include "SVGResources.h" #include "SVGStyledElement.h" @@ -100,8 +101,7 @@ bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, UNUSED_PARAM(resourceMode); #endif - applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context); - return true; + return applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context); } bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const FloatRect& objectBoundingBox) @@ -163,47 +163,67 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons if (!m_clipper.contains(object)) m_clipper.set(object, new ClipperData); + bool shouldCreateClipData = false; ClipperData* clipperData = m_clipper.get(object); if (!clipperData->clipMaskImage) { if (pathOnlyClipping(context, objectBoundingBox)) return true; - createClipData(clipperData, objectBoundingBox, repaintRect); + shouldCreateClipData = true; + } + + AffineTransform absoluteTransform; + SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); + + FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect); + FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(object, absoluteTargetRect); + + if (shouldCreateClipData && !clampedAbsoluteTargetRect.isEmpty()) { + if (!SVGImageBufferTools::createImageBuffer(absoluteTargetRect, clampedAbsoluteTargetRect, clipperData->clipMaskImage, DeviceRGB)) + return false; + + GraphicsContext* maskContext = clipperData->clipMaskImage->context(); + ASSERT(maskContext); + + // The save/restore pair is needed for clipToImageBuffer - it doesn't work without it on non-Cg platforms. + maskContext->save(); + maskContext->translate(-clampedAbsoluteTargetRect.x(), -clampedAbsoluteTargetRect.y()); + maskContext->concatCTM(absoluteTransform); + + // clipPath can also be clipped by another clipPath. + if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) { + if (RenderSVGResourceClipper* clipper = resources->clipper()) { + if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) { + maskContext->restore(); + return false; + } + } + } + + drawContentIntoMaskImage(clipperData, objectBoundingBox); + maskContext->restore(); } if (!clipperData->clipMaskImage) return false; - context->clipToImageBuffer(clipperData->clipMaskImage.get(), repaintRect); + SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, clipperData->clipMaskImage); return true; } -bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const FloatRect& objectBoundingBox, const FloatRect& repaintRect) +bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox) { - IntRect clipMaskRect = enclosingIntRect(repaintRect); - clipperData->clipMaskImage = ImageBuffer::create(clipMaskRect.size()); - if (!clipperData->clipMaskImage) - return false; + ASSERT(clipperData); + ASSERT(clipperData->clipMaskImage); GraphicsContext* maskContext = clipperData->clipMaskImage->context(); ASSERT(maskContext); - maskContext->save(); - maskContext->translate(-repaintRect.x(), -repaintRect.y()); - - // clipPath can also be clipped by another clipPath. - if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) { - if (RenderSVGResourceClipper* clipper = resources->clipper()) { - if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) { - maskContext->restore(); - return false; - } - } - } - + AffineTransform maskContentTransformation; SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node()); if (clipPath->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { - maskContext->translate(objectBoundingBox.x(), objectBoundingBox.y()); - maskContext->scale(objectBoundingBox.size()); + maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y()); + maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + maskContext->concatCTM(maskContentTransformation); } // Draw all clipPath children into a global mask. @@ -251,16 +271,14 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl renderer->setStyle(newRenderStyle.release()); // In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule. - // We hsve to pass the <use> renderer itself to renderSubtreeToImage() to apply it's x/y/transform/etc. values when rendering. + // We have to pass the <use> renderer itself to renderSubtreeToImageBuffer() to apply it's x/y/transform/etc. values when rendering. // So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above. - SVGRenderSupport::renderSubtreeToImage(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer); + SVGImageBufferTools::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransformation); renderer->setStyle(oldRenderStyle.release()); m_invalidationBlocked = false; } - maskContext->restore(); - return true; } diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h index 0f68c67..20153e9 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.h +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -65,7 +65,7 @@ private: // applyResource directly and use the rects from the object, since they are empty for RenderSVGResources bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*); bool pathOnlyClipping(GraphicsContext*, const FloatRect&); - bool createClipData(ClipperData*, const FloatRect&, const FloatRect&); + bool drawContentIntoMaskImage(ClipperData*, const FloatRect& objectBoundingBox); void calculateClipContentRepaintRect(); bool m_invalidationBlocked; diff --git a/WebCore/rendering/RenderSVGResourceContainer.cpp b/WebCore/rendering/RenderSVGResourceContainer.cpp index 5652dcc..f33eb85 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.cpp +++ b/WebCore/rendering/RenderSVGResourceContainer.cpp @@ -184,7 +184,7 @@ AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderOb SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); AffineTransform transform = resourceTransform; - transform.multiply(element->getScreenCTM()); + transform.multiply(element->getScreenCTM(SVGLocatable::DisallowStyleUpdate)); return transform; } diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index d29192a..1c33de4 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -80,35 +80,49 @@ static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object); ASSERT(textRootBlock); - AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); + AffineTransform absoluteTransform; + SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform); + FloatRect absoluteTargetRect = absoluteTransform.mapRect(textRootBlock->repaintRectInLocalCoordinates()); + FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(textRootBlock, absoluteTargetRect); + if (clampedAbsoluteTargetRect.isEmpty()) + return false; OwnPtr<ImageBuffer> maskImage; - if (!SVGImageBufferTools::createImageBuffer(absoluteTransform, absoluteTargetRect, maskImage, DeviceRGB)) + if (!SVGImageBufferTools::createImageBuffer(absoluteTargetRect, clampedAbsoluteTargetRect, maskImage, DeviceRGB)) return false; + GraphicsContext* maskImageContext = maskImage->context(); + ASSERT(maskImageContext); + + maskImageContext->translate(-clampedAbsoluteTargetRect.x(), -clampedAbsoluteTargetRect.y()); + maskImageContext->concatCTM(absoluteTransform); + ASSERT(maskImage); savedContext = context; - context = maskImage->context(); + context = maskImageContext; imageBuffer = maskImage.release(); return true; } static inline AffineTransform clipToTextMask(GraphicsContext* context, OwnPtr<ImageBuffer>& imageBuffer, - FloatRect& repaintRect, + FloatRect& targetRect, const RenderObject* object, GradientData* gradientData) { const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object); ASSERT(textRootBlock); - repaintRect = textRootBlock->repaintRectInLocalCoordinates(); + targetRect = textRootBlock->repaintRectInLocalCoordinates(); + + AffineTransform absoluteTransform; + SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform); - AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); - FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect); + FloatRect absoluteTargetRect = absoluteTransform.mapRect(targetRect); + FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(textRootBlock, absoluteTargetRect); - SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, absoluteTargetRect, imageBuffer.get()); + SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, imageBuffer); AffineTransform matrix; if (gradientData->boundingBoxMode) { @@ -216,11 +230,11 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics context = m_savedContext; m_savedContext = 0; - FloatRect repaintRect; - gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, repaintRect, object, gradientData)); + FloatRect targetRect; + gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, object, gradientData)); context->setFillGradient(gradientData->gradient); - context->fillRect(repaintRect); + context->fillRect(targetRect); m_imageBuffer.clear(); } #else diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 9713dd6..3e81929 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -96,43 +96,50 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, MaskerData* maskerData = m_masker.get(object); - AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context)); - FloatRect maskRect = absoluteTransform.mapRect(object->repaintRectInLocalCoordinates()); + AffineTransform absoluteTransform; + SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); - if (!maskerData->maskImage && !maskRect.isEmpty()) { + FloatRect absoluteTargetRect = absoluteTransform.mapRect(object->repaintRectInLocalCoordinates()); + FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(object, absoluteTargetRect); + + if (!maskerData->maskImage && !clampedAbsoluteTargetRect.isEmpty()) { SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); if (!maskElement) return false; - if (!SVGImageBufferTools::createImageBuffer(absoluteTransform, maskRect, maskerData->maskImage, LinearRGB)) + if (!SVGImageBufferTools::createImageBuffer(absoluteTargetRect, clampedAbsoluteTargetRect, maskerData->maskImage, LinearRGB)) return false; - ASSERT(maskerData->maskImage); - drawContentIntoMaskImage(maskRect, maskerData, maskElement, object); + GraphicsContext* maskImageContext = maskerData->maskImage->context(); + ASSERT(maskImageContext); + + // The save/restore pair is needed for clipToImageBuffer - it doesn't work without it on non-Cg platforms. + maskImageContext->save(); + maskImageContext->translate(-clampedAbsoluteTargetRect.x(), -clampedAbsoluteTargetRect.y()); + maskImageContext->concatCTM(absoluteTransform); + + drawContentIntoMaskImage(maskerData, maskElement, object); } if (!maskerData->maskImage) return false; - SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, maskRect, maskerData->maskImage.get()); + SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, maskerData->maskImage); return true; } -void RenderSVGResourceMasker::drawContentIntoMaskImage(const FloatRect& maskRect, MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) +void RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) { - IntRect maskImageRect = enclosingIntRect(maskRect); - maskImageRect.setLocation(IntPoint()); + GraphicsContext* maskImageContext = maskerData->maskImage->context(); + ASSERT(maskImageContext); // Eventually adjust the mask image context according to the target objectBoundingBox. + AffineTransform maskContentTransformation; if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { - GraphicsContext* maskImageContext = maskerData->maskImage->context(); - ASSERT(maskImageContext); - FloatRect objectBoundingBox = object->objectBoundingBox(); - AffineTransform contextTransform; - contextTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); - contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - maskImageContext->concatCTM(contextTransform); + maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y()); + maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + maskImageContext->concatCTM(maskContentTransformation); } // Draw the content into the ImageBuffer. @@ -143,14 +150,17 @@ void RenderSVGResourceMasker::drawContentIntoMaskImage(const FloatRect& maskRect RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; - SVGRenderSupport::renderSubtreeToImage(maskerData->maskImage.get(), renderer); + SVGImageBufferTools::renderSubtreeToImageBuffer(maskerData->maskImage.get(), renderer, maskContentTransformation); } + maskImageContext->restore(); + #if !PLATFORM(CG) maskerData->maskImage->transformColorSpace(DeviceRGB, LinearRGB); #endif - // create the luminance mask + // Create the luminance mask. + IntRect maskImageRect(IntPoint(), maskerData->maskImage->size()); RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect)); CanvasPixelArray* srcPixelArray(imageData->data()); diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index f2d8cb2..fddecd0 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -58,7 +58,7 @@ public: static RenderSVGResourceType s_resourceType; private: - void drawContentIntoMaskImage(const FloatRect& maskRect, MaskerData*, const SVGMaskElement*, RenderObject*); + void drawContentIntoMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*); void calculateMaskContentRepaintRect(); FloatRect m_maskContentBoundaries; diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index f4f5cf4..ccbdaca 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -27,6 +27,8 @@ #include "FrameView.h" #include "GraphicsContext.h" #include "PatternAttributes.h" +#include "RenderSVGRoot.h" +#include "SVGImageBufferTools.h" #include "SVGRenderSupport.h" namespace WebCore { @@ -75,7 +77,7 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* ASSERT(resourceMode != ApplyToDefaultMode); // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further. - // Otherwhise the call to collectPatternAttributes() in createTileImage(), may cause the SVG DOM property + // Otherwhise the call to collectPatternAttributes() below, may cause the SVG DOM property // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash. SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node()); @@ -89,17 +91,43 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* PatternData* patternData = m_pattern.get(object); if (!patternData->pattern) { - // Create tile image - OwnPtr<ImageBuffer> tileImage = createTileImage(patternData, patternElement, object); + PatternAttributes attributes = patternElement->collectPatternProperties(); + + // If we couldn't determine the pattern content element root, stop here. + if (!attributes.patternContentElement()) + return false; + + // Compute all necessary transformations to build the tile image & the pattern. + FloatRect tileBoundaries; + AffineTransform tileImageTransform = buildTileImageTransform(object, attributes, patternElement, tileBoundaries); + + AffineTransform absoluteTransform; + SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); + + FloatRect absoluteTileBoundaries = absoluteTransform.mapRect(tileBoundaries); + + // Build tile image. + OwnPtr<ImageBuffer> tileImage = createTileImage(object, attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform); if (!tileImage) return false; - // Create pattern object - buildPattern(patternData, tileImage.release()); + RefPtr<Image> copiedImage = tileImage->copyImage(); + if (!copiedImage) + return false; + // Build pattern. + patternData->pattern = Pattern::create(copiedImage, true, true); if (!patternData->pattern) return false; + // Compute pattern space transformation. + patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y()); + patternData->transform.scale(tileBoundaries.width() / absoluteTileBoundaries.width(), tileBoundaries.height() / absoluteTileBoundaries.height()); + + AffineTransform patternTransform = attributes.patternTransform(); + if (!patternTransform.isIdentity()) + patternData->transform.multiply(patternTransform); + patternData->pattern->setPatternSpaceTransform(patternData->transform); } @@ -155,13 +183,15 @@ void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext* context->restore(); } -static inline FloatRect calculatePatternBoundaries(PatternAttributes& attributes, +static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attributes, const FloatRect& objectBoundingBox, const SVGPatternElement* patternElement) { + ASSERT(patternElement); + if (attributes.boundingBoxMode()) - return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width(), - attributes.y().valueAsPercentage() * objectBoundingBox.height(), + return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(), + attributes.y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(), attributes.width().valueAsPercentage() * objectBoundingBox.width(), attributes.height().valueAsPercentage() * objectBoundingBox.height()); @@ -171,175 +201,77 @@ static inline FloatRect calculatePatternBoundaries(PatternAttributes& attributes attributes.height().value(patternElement)); } -FloatRect RenderSVGResourcePattern::calculatePatternBoundariesIncludingOverflow(PatternAttributes& attributes, - const FloatRect& objectBoundingBox, - const AffineTransform& viewBoxCTM, - const FloatRect& patternBoundaries) const +AffineTransform RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer, + const PatternAttributes& attributes, + const SVGPatternElement* patternElement, + FloatRect& patternBoundaries) const { - // Eventually calculate the pattern content boundaries (only needed with overflow="visible"). - FloatRect patternContentBoundaries; - - const RenderStyle* style = this->style(); - if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) { - for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { - if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyledTransformable() || !node->renderer()) - continue; - patternContentBoundaries.unite(node->renderer()->repaintRectInLocalCoordinates()); - } - } + ASSERT(renderer); + ASSERT(patternElement); - if (patternContentBoundaries.isEmpty()) - return patternBoundaries; + FloatRect objectBoundingBox = renderer->objectBoundingBox(); + patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); - FloatRect patternBoundariesIncludingOverflow = patternBoundaries; + AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(patternElement->viewBox(), patternElement->preserveAspectRatio(), patternBoundaries.width(), patternBoundaries.height()); + AffineTransform tileImageTransform; - // Respect objectBoundingBoxMode for patternContentUnits, if viewBox is not set. + // Apply viewBox/objectBoundingBox transformations. if (!viewBoxCTM.isIdentity()) - patternContentBoundaries = viewBoxCTM.mapRect(patternContentBoundaries); - else if (attributes.boundingBoxModeContent()) - patternContentBoundaries = FloatRect(patternContentBoundaries.x() * objectBoundingBox.width(), - patternContentBoundaries.y() * objectBoundingBox.height(), - patternContentBoundaries.width() * objectBoundingBox.width(), - patternContentBoundaries.height() * objectBoundingBox.height()); - - patternBoundariesIncludingOverflow.unite(patternContentBoundaries); - return patternBoundariesIncludingOverflow; -} - -// FIXME: This method should be removed. RenderSVGResourcePatterns usage of it is just wrong. -static inline void clampImageBufferSizeToViewport(FrameView* frameView, IntSize& size) -{ - if (!frameView) - return; - - int viewWidth = frameView->visibleWidth(); - int viewHeight = frameView->visibleHeight(); - - if (size.width() > viewWidth) - size.setWidth(viewWidth); + tileImageTransform = viewBoxCTM; + else if (attributes.boundingBoxModeContent()) { + tileImageTransform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + tileImageTransform.scale(objectBoundingBox.width(), objectBoundingBox.height()); + } - if (size.height() > viewHeight) - size.setHeight(viewHeight); + return tileImageTransform; } -PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* patternData, - const SVGPatternElement* patternElement, - RenderObject* object) const +PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(RenderObject* object, + const PatternAttributes& attributes, + const FloatRect& tileBoundaries, + const FloatRect& absoluteTileBoundaries, + const AffineTransform& tileImageTransform) const { - PatternAttributes attributes = patternElement->collectPatternProperties(); - - // If we couldn't determine the pattern content element root, stop here. - if (!attributes.patternContentElement()) - return 0; - - FloatRect objectBoundingBox = object->objectBoundingBox(); - FloatRect patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); - AffineTransform patternTransform = attributes.patternTransform(); + ASSERT(object); - AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(patternElement->viewBox(), - patternElement->preserveAspectRatio(), - patternBoundaries.width(), - patternBoundaries.height()); + // Clamp tile image size against SVG viewport size, as last resort, to avoid allocating huge image buffers. + FloatRect contentBoxRect = SVGRenderSupport::findTreeRootObject(object)->contentBoxRect(); - FloatRect patternBoundariesIncludingOverflow = calculatePatternBoundariesIncludingOverflow(attributes, - objectBoundingBox, - viewBoxCTM, - patternBoundaries); + FloatRect clampedAbsoluteTileBoundaries = absoluteTileBoundaries; + if (clampedAbsoluteTileBoundaries.width() > contentBoxRect.width()) + clampedAbsoluteTileBoundaries.setWidth(contentBoxRect.width()); - IntSize imageSize(lroundf(patternBoundariesIncludingOverflow.width()), lroundf(patternBoundariesIncludingOverflow.height())); + if (clampedAbsoluteTileBoundaries.height() > contentBoxRect.height()) + clampedAbsoluteTileBoundaries.setHeight(contentBoxRect.height()); - // FIXME: We should be able to clip this more, needs investigation - clampImageBufferSizeToViewport(object->document()->view(), imageSize); + OwnPtr<ImageBuffer> tileImage; - // Don't create ImageBuffers with image size of 0 - if (imageSize.isEmpty()) - return 0; + if (!SVGImageBufferTools::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, DeviceRGB)) + return PassOwnPtr<ImageBuffer>(); - OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(imageSize); + GraphicsContext* tileImageContext = tileImage->context(); + ASSERT(tileImageContext); - GraphicsContext* context = tileImage->context(); - ASSERT(context); + // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation). + tileImageContext->scale(FloatSize(absoluteTileBoundaries.width() / tileBoundaries.width(), + absoluteTileBoundaries.height() / tileBoundaries.height())); - context->save(); + // Apply tile image transformations. + if (!tileImageTransform.isIdentity()) + tileImageContext->concatCTM(tileImageTransform); - // Translate to pattern start origin - if (patternBoundariesIncludingOverflow.location() != patternBoundaries.location()) { - context->translate(patternBoundaries.x() - patternBoundariesIncludingOverflow.x(), - patternBoundaries.y() - patternBoundariesIncludingOverflow.y()); + AffineTransform contentTransformation; - patternBoundaries.setLocation(patternBoundariesIncludingOverflow.location()); - } - - // Process viewBox or boundingBoxModeContent correction - if (!viewBoxCTM.isIdentity()) - context->concatCTM(viewBoxCTM); - else if (attributes.boundingBoxModeContent()) { - context->translate(objectBoundingBox.x(), objectBoundingBox.y()); - context->scale(FloatSize(objectBoundingBox.width(), objectBoundingBox.height())); - } - - // Render subtree into ImageBuffer + // Draw the content into the ImageBuffer. for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) continue; - SVGRenderSupport::renderSubtreeToImage(tileImage.get(), node->renderer()); + SVGImageBufferTools::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation); } - patternData->boundaries = patternBoundaries; - - // Compute pattern transformation - patternData->transform.translate(patternBoundaries.x(), patternBoundaries.y()); - patternData->transform.multiply(patternTransform); - - context->restore(); return tileImage.release(); } -void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr<ImageBuffer> tileImage) const -{ - RefPtr<Image> copiedImage = tileImage->copyImage(); - if (!copiedImage) { - patternData->pattern = 0; - return; - } - - IntRect tileRect = copiedImage->rect(); - if (tileRect.width() <= patternData->boundaries.width() && tileRect.height() <= patternData->boundaries.height()) { - patternData->pattern = Pattern::create(copiedImage, true, true); - return; - } - - // Draw the first cell of the pattern manually to support overflow="visible" on all platforms. - int tileWidth = static_cast<int>(patternData->boundaries.width() + 0.5f); - int tileHeight = static_cast<int>(patternData->boundaries.height() + 0.5f); - - // Don't create ImageBuffers with image size of 0 - if (!tileWidth || !tileHeight) { - patternData->pattern = 0; - return; - } - - OwnPtr<ImageBuffer> newTileImage = ImageBuffer::create(IntSize(tileWidth, tileHeight)); - GraphicsContext* newTileImageContext = newTileImage->context(); - - int numY = static_cast<int>(ceilf(tileRect.height() / tileHeight)) + 1; - int numX = static_cast<int>(ceilf(tileRect.width() / tileWidth)) + 1; - - newTileImageContext->save(); - newTileImageContext->translate(-patternData->boundaries.width() * numX, -patternData->boundaries.height() * numY); - for (int i = numY; i > 0; --i) { - newTileImageContext->translate(0, patternData->boundaries.height()); - for (int j = numX; j > 0; --j) { - newTileImageContext->translate(patternData->boundaries.width(), 0); - newTileImageContext->drawImage(copiedImage.get(), style()->colorSpace(), tileRect, tileRect); - } - newTileImageContext->translate(-patternData->boundaries.width() * numX, 0); - } - newTileImageContext->restore(); - - patternData->pattern = Pattern::create(newTileImage->copyImage(), true, true); -} - } #endif diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index 52bf09d..9a067c2 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -38,7 +38,6 @@ namespace WebCore { struct PatternData { RefPtr<Pattern> pattern; - FloatRect boundaries; AffineTransform transform; }; @@ -62,10 +61,10 @@ public: static RenderSVGResourceType s_resourceType; private: - PassOwnPtr<ImageBuffer> createTileImage(PatternData*, const SVGPatternElement*, RenderObject*) const; - void buildPattern(PatternData*, PassOwnPtr<ImageBuffer> tileImage) const; - FloatRect calculatePatternBoundariesIncludingOverflow(PatternAttributes&, const FloatRect& objectBoundingBox, - const AffineTransform& viewBoxCTM, const FloatRect& patternBoundaries) const; + AffineTransform buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement*, FloatRect& patternBoundaries) const; + + PassOwnPtr<ImageBuffer> createTileImage(RenderObject*, const PatternAttributes&, const FloatRect& tileBoundaries, + const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform) const; HashMap<RenderObject*, PatternData*> m_pattern; }; diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 591b1ac..aef807b 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -29,7 +29,7 @@ #include "Frame.h" #include "HTMLInputElement.h" #include "HTMLNames.h" -#include "LegacyHTMLTreeBuilder.h" +#include "HTMLTreeBuilder.h" #include "MediaControlElements.h" #include "MouseEvent.h" #include "RenderLayer.h" @@ -58,7 +58,7 @@ static double sliderPosition(HTMLInputElement* element) class SliderThumbElement : public ShadowBlockElement { public: - static PassRefPtr<SliderThumbElement> create(Node* shadowParent); + static PassRefPtr<SliderThumbElement> create(HTMLElement* shadowParent); bool inDragMode() const { return m_inDragMode; } @@ -66,19 +66,19 @@ public: virtual void detach(); private: - SliderThumbElement(Node* shadowParent); + SliderThumbElement(HTMLElement* shadowParent); FloatPoint m_offsetToThumb; bool m_inDragMode; }; -inline SliderThumbElement::SliderThumbElement(Node* shadowParent) +inline SliderThumbElement::SliderThumbElement(HTMLElement* shadowParent) : ShadowBlockElement(shadowParent) , m_inDragMode(false) { } -inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(Node* shadowParent) +inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(HTMLElement* shadowParent) { return adoptRef(new SliderThumbElement(shadowParent)); } @@ -309,7 +309,7 @@ void RenderSlider::updateFromElement() { // Layout will take care of the thumb's size and position. if (!m_thumb) { - m_thumb = SliderThumbElement::create(node()); + m_thumb = SliderThumbElement::create(static_cast<HTMLElement*>(node())); RefPtr<RenderStyle> thumbStyle = createThumbStyle(style()); m_thumb->setRenderer(m_thumb->createRenderer(renderArena(), thumbStyle.get())); m_thumb->renderer()->setStyle(thumbStyle.release()); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 5f8c788..9098bab 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -145,7 +145,7 @@ void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBloc // For non-search fields, there is no intermediate innerBlock as the shadow node. // m_innerText will be the shadow node in that case. RenderStyle* parentStyle = innerBlock ? innerBlock->renderer()->style() : style(); - m_innerText = TextControlInnerTextElement::create(document(), innerBlock ? 0 : node()); + m_innerText = TextControlInnerTextElement::create(document(), innerBlock ? 0 : static_cast<HTMLElement*>(node())); m_innerText->attachInnerElement(innerBlock ? innerBlock : node(), createInnerTextStyle(parentStyle), renderArena()); } } diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index ed5c2f4..b27a91a 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -610,17 +610,17 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded() #if ENABLE(INPUT_SPEECH) if (inputElement()->isSpeechEnabled() && !m_speechButton) { // Create the speech button element. - m_speechButton = InputFieldSpeechButtonElement::create(node()); + m_speechButton = InputFieldSpeechButtonElement::create(static_cast<HTMLElement*>(node())); m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena()); } #endif bool hasSpinButton = inputElement()->hasSpinButton(); if (hasSpinButton && !m_innerSpinButton) { - m_innerSpinButton = SpinButtonElement::create(node()); + m_innerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node())); m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena()); } if (hasSpinButton && !m_outerSpinButton) { - m_outerSpinButton = SpinButtonElement::create(node()); + m_outerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node())); m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena()); } return; @@ -628,18 +628,18 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded() if (!m_innerBlock) { // Create the inner block element - m_innerBlock = TextControlInnerElement::create(node()); + m_innerBlock = TextControlInnerElement::create(static_cast<HTMLElement*>(node())); m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena()); } #if ENABLE(INPUT_SPEECH) if (inputElement()->isSpeechEnabled() && !m_speechButton) { // Create the speech button element. - m_speechButton = InputFieldSpeechButtonElement::create(node()); + m_speechButton = InputFieldSpeechButtonElement::create(static_cast<HTMLElement*>(node())); m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena()); } #endif if (inputElement()->hasSpinButton() && !m_outerSpinButton) { - m_outerSpinButton = SpinButtonElement::create(node()); + m_outerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node())); m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena()); } diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index 799b206..8145cac 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -71,12 +71,18 @@ public: enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld }; void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld); void clearSelection(); - virtual RenderObject* selectionStart() const { return m_selectionStart; } - virtual RenderObject* selectionEnd() const { return m_selectionEnd; } + RenderObject* selectionStart() const { return m_selectionStart; } + RenderObject* selectionEnd() const { return m_selectionEnd; } + IntRect selectionBounds(bool clipToVisibleContent = true) const; + void selectionStartEnd(int& startPos, int& endPos) const; bool printing() const; void setPrintImages(bool enable) { m_printImages = enable; } bool printImages() const { return m_printImages; } + + IntRect printRect() const { return m_printRect; } + void setPrintRect(const IntRect& r) { m_printRect = r; } + 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; } @@ -88,8 +94,6 @@ public: virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); - IntRect selectionBounds(bool clipToVisibleContent = true) const; - #if USE(ACCELERATED_COMPOSITING) void setMaximalOutlineSize(int o); #else @@ -99,11 +103,6 @@ public: virtual IntRect viewRect() const; - void selectionStartEnd(int& startPos, int& endPos) const; - - IntRect printRect() const { return m_printRect; } - void setPrintRect(const IntRect& r) { m_printRect = r; } - void updateWidgetPositions(); void addWidget(RenderWidget*); void removeWidget(RenderWidget*); diff --git a/WebCore/rendering/SVGImageBufferTools.cpp b/WebCore/rendering/SVGImageBufferTools.cpp index 5b45ccc..709bf10 100644 --- a/WebCore/rendering/SVGImageBufferTools.cpp +++ b/WebCore/rendering/SVGImageBufferTools.cpp @@ -22,50 +22,118 @@ #if ENABLE(SVG) #include "SVGImageBufferTools.h" +#include "FrameView.h" #include "GraphicsContext.h" #include "RenderObject.h" +#include "RenderSVGContainer.h" +#include "RenderSVGRoot.h" namespace WebCore { -AffineTransform SVGImageBufferTools::absoluteTransformFromContext(GraphicsContext* context) +static AffineTransform& currentContentTransformation() { - // Extract current transformation matrix used in the original context. Note that this coordinate - // system is flipped compared to SVGs internal coordinate system, done in WebKit level. Fix - // this transformation by flipping the y component. - return context->getCTM() * AffineTransform().flipY(); + DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ()); + return s_currentContentTransformation; } -bool SVGImageBufferTools::createImageBuffer(const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ImageColorSpace colorSpace) +void SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform) { - IntRect imageRect = enclosingIntRect(absoluteTargetRect); - if (imageRect.isEmpty()) + const RenderObject* current = renderer; + ASSERT(current); + + absoluteTransform = currentContentTransformation(); + while (current) { + absoluteTransform.multiply(current->localToParentTransform()); + if (current->isSVGRoot()) + break; + current = current->parent(); + } +} + +bool SVGImageBufferTools::createImageBuffer(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ImageColorSpace colorSpace) +{ + IntSize imageSize(roundedImageBufferSize(clampedAbsoluteTargetRect.size())); + IntSize unclampedImageSize(SVGImageBufferTools::roundedImageBufferSize(absoluteTargetRect.size())); + + // Don't create empty ImageBuffers. + if (imageSize.isEmpty()) return false; - // Allocate an image buffer as big as the absolute unclipped size of the object - OwnPtr<ImageBuffer> image = ImageBuffer::create(imageRect.size(), colorSpace); + OwnPtr<ImageBuffer> image = ImageBuffer::create(imageSize, colorSpace); if (!image) return false; GraphicsContext* imageContext = image->context(); + ASSERT(imageContext); - // Transform the mask image coordinate system to absolute screen coordinates - imageContext->translate(-absoluteTargetRect.x(), -absoluteTargetRect.y()); - imageContext->concatCTM(absoluteTransform); + // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer. + imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height())); imageBuffer = image.release(); return true; } -void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, ImageBuffer* imageBuffer) +void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation) +{ + ASSERT(item); + ASSERT(image); + ASSERT(image->context()); + + PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0); + + // FIXME: isSVGContainer returns true for RenderSVGViewportContainer, so if this is ever + // called with one of those, we will read from the wrong offset in an object due to a bad cast. + RenderSVGContainer* svgContainer = 0; + if (item && item->isSVGContainer()) + svgContainer = toRenderSVGContainer(item); + + bool drawsContents = svgContainer ? svgContainer->drawsContents() : false; + if (svgContainer && !drawsContents) + svgContainer->setDrawsContents(true); + + AffineTransform& contentTransformation = currentContentTransformation(); + AffineTransform savedContentTransformation = contentTransformation; + contentTransformation.multiply(subtreeContentTransformation); + + item->layoutIfNeeded(); + item->paint(info, 0, 0); + + contentTransformation = savedContentTransformation; + + if (svgContainer && !drawsContents) + svgContainer->setDrawsContents(false); +} + +void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer) { ASSERT(context); ASSERT(imageBuffer); - // The mask image has been created in the device coordinate space, as the image should not be scaled. - // So the actual masking process has to be done in the device coordinate space as well. + // The mask image has been created in the absolute coordinate space, as the image should not be scaled. + // So the actual masking process has to be done in the absolute coordinate space as well. context->concatCTM(absoluteTransform.inverse()); - context->clipToImageBuffer(imageBuffer, absoluteTargetRect); + context->clipToImageBuffer(imageBuffer.get(), clampedAbsoluteTargetRect); context->concatCTM(absoluteTransform); + + // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the + // resulting image buffer as the parent resource already caches the result. + if (!currentContentTransformation().isIdentity()) + imageBuffer.clear(); +} + +IntSize SVGImageBufferTools::roundedImageBufferSize(const FloatSize& size) +{ + return IntSize(static_cast<int>(lroundf(size.width())), static_cast<int>(lroundf(size.height()))); +} + +FloatRect SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(const RenderObject* renderer, const FloatRect& absoluteTargetRect) +{ + ASSERT(renderer); + + const RenderSVGRoot* svgRoot = SVGRenderSupport::findTreeRootObject(renderer); + FloatRect clampedAbsoluteTargetRect = absoluteTargetRect; + clampedAbsoluteTargetRect.intersect(svgRoot->contentBoxRect()); + return clampedAbsoluteTargetRect; } } diff --git a/WebCore/rendering/SVGImageBufferTools.h b/WebCore/rendering/SVGImageBufferTools.h index bdbcb1c..8894aae 100644 --- a/WebCore/rendering/SVGImageBufferTools.h +++ b/WebCore/rendering/SVGImageBufferTools.h @@ -28,15 +28,19 @@ namespace WebCore { class AffineTransform; class FloatRect; +class FloatSize; class GraphicsContext; class RenderObject; class SVGImageBufferTools : public Noncopyable { public: - static bool createImageBuffer(const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, OwnPtr<ImageBuffer>&, ImageColorSpace); - static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& absoluteTargetRect, ImageBuffer*); + static bool createImageBuffer(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>&, ImageColorSpace); + static void renderSubtreeToImageBuffer(ImageBuffer*, RenderObject*, const AffineTransform&); + static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>&); - static AffineTransform absoluteTransformFromContext(GraphicsContext*); + static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform); + static FloatRect clampedAbsoluteTargetRectForRenderer(const RenderObject*, const FloatRect& absoluteTargetRect); + static IntSize roundedImageBufferSize(const FloatSize&); private: SVGImageBufferTools() { } diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index f5bbe5b..ccba5b4 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -408,7 +408,7 @@ void SVGInlineTextBox::computeTextMatchMarkerRect(RenderStyle* style) return; Document* document = renderer()->document(); - Vector<DocumentMarker> markers = document->markersForNode(renderer()->node()); + Vector<DocumentMarker> markers = document->markers()->markersForNode(renderer()->node()); Vector<DocumentMarker>::iterator markerEnd = markers.end(); for (Vector<DocumentMarker>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) { @@ -430,7 +430,7 @@ void SVGInlineTextBox::computeTextMatchMarkerRect(RenderStyle* style) if (!m_chunkTransformation.isIdentity()) markerRect = m_chunkTransformation.mapRect(markerRect); - document->setRenderedRectForMarker(node, marker, renderer()->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); + document->markers()->setRenderedRectForMarker(node, marker, renderer()->localToAbsoluteQuad(markerRect).enclosingBoundingBox()); } } diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index e265b2b..12d6d77 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -33,7 +33,6 @@ #include "NodeRenderStyle.h" #include "RenderLayer.h" #include "RenderPath.h" -#include "RenderSVGContainer.h" #include "RenderSVGResource.h" #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" @@ -116,8 +115,10 @@ bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo return false; } - if (RenderSVGResourceClipper* clipper = resources->clipper()) - clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); + if (RenderSVGResourceClipper* clipper = resources->clipper()) { + if (!clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) + return false; + } #if ENABLE(FILTERS) if (RenderSVGResourceFilter* filter = resources->filter()) { @@ -163,37 +164,6 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p paintInfo.context->endTransparencyLayer(); } -void SVGRenderSupport::renderSubtreeToImage(ImageBuffer* image, RenderObject* item) -{ - ASSERT(item); - ASSERT(image); - ASSERT(image->context()); - - // FIXME: This sets the rect to the viewable area of the current frame. This - // is used to support text drawings to the ImageBuffer. See bug 30399. - IntRect rect; - FrameView* frameView = item->document()->view(); - if (frameView) - rect = IntRect(0, 0, frameView->visibleWidth(), frameView->visibleHeight()); - PaintInfo info(image->context(), rect, PaintPhaseForeground, 0, 0, 0); - - // FIXME: isSVGContainer returns true for RenderSVGViewportContainer, so if this is ever - // called with one of those, we will read from the wrong offset in an object due to a bad cast. - RenderSVGContainer* svgContainer = 0; - if (item && item->isSVGContainer()) - svgContainer = toRenderSVGContainer(item); - - bool drawsContents = svgContainer ? svgContainer->drawsContents() : false; - if (svgContainer && !drawsContents) - svgContainer->setDrawsContents(true); - - item->layoutIfNeeded(); - item->paint(info, 0, 0); - - if (svgContainer && !drawsContents) - svgContainer->setDrawsContents(false); -} - FloatRect SVGRenderSupport::computeContainerBoundingBox(const RenderObject* container, ContainerBoundingBoxMode mode) { FloatRect boundingBox; @@ -219,7 +189,7 @@ FloatRect SVGRenderSupport::computeContainerBoundingBox(const RenderObject* cont return boundingBox; } -static inline RenderSVGRoot* svgRootTreeObject(RenderObject* start) +const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* start) { while (start && !start->isSVGRoot()) start = start->parent(); @@ -241,7 +211,7 @@ static inline void invalidateResourcesOfChildren(RenderObject* start) void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) { - bool layoutSizeChanged = svgRootTreeObject(start)->isLayoutSizeChanged(); + bool layoutSizeChanged = findTreeRootObject(start)->isLayoutSizeChanged(); HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index 576475b..2de1e99 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -36,6 +36,7 @@ class ImageBuffer; class RenderBoxModelObject; class RenderObject; class RenderStyle; +class RenderSVGRoot; class TransformState; // SVGRendererSupport is a helper class sharing code between all SVG renderers. @@ -72,14 +73,12 @@ public: static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed); static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&); - // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. - static void renderSubtreeToImage(ImageBuffer*, RenderObject*); - // Shared between SVG renderers and resources. static void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*); // FIXME: These methods do not belong here. static const RenderObject* findTextRootObject(const RenderObject* start); + static const RenderSVGRoot* findTreeRootObject(const RenderObject* start); private: // This class is not constructable. diff --git a/WebCore/rendering/SVGShadowTreeElements.cpp b/WebCore/rendering/SVGShadowTreeElements.cpp index f26f87e..311874c 100644 --- a/WebCore/rendering/SVGShadowTreeElements.cpp +++ b/WebCore/rendering/SVGShadowTreeElements.cpp @@ -45,7 +45,7 @@ FloatSize SVGShadowTreeContainerElement::containerTranslation() const } // SVGShadowTreeRootElement -SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, Node* shadowParent) +SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, Element* shadowParent) : SVGShadowTreeContainerElement(document) , m_shadowParent(shadowParent) { diff --git a/WebCore/rendering/SVGShadowTreeElements.h b/WebCore/rendering/SVGShadowTreeElements.h index ed42e89..7611b8a 100644 --- a/WebCore/rendering/SVGShadowTreeElements.h +++ b/WebCore/rendering/SVGShadowTreeElements.h @@ -49,16 +49,16 @@ private: class SVGShadowTreeRootElement : public SVGShadowTreeContainerElement { public: - SVGShadowTreeRootElement(Document*, Node* shadowParent); + SVGShadowTreeRootElement(Document*, Element* shadowParent); virtual ~SVGShadowTreeRootElement(); virtual bool isShadowNode() const { return m_shadowParent; } - virtual Node* shadowParentNode() { return m_shadowParent; } + virtual ContainerNode* shadowParentNode() { return m_shadowParent; } void attachElement(PassRefPtr<RenderStyle>, RenderArena*); private: - Node* m_shadowParent; + ContainerNode* m_shadowParent; }; } diff --git a/WebCore/rendering/ShadowElement.cpp b/WebCore/rendering/ShadowElement.cpp index 55a4b5c..c52ce17 100644 --- a/WebCore/rendering/ShadowElement.cpp +++ b/WebCore/rendering/ShadowElement.cpp @@ -29,12 +29,12 @@ namespace WebCore { using namespace HTMLNames; -PassRefPtr<ShadowBlockElement> ShadowBlockElement::create(Node* shadowParent) +PassRefPtr<ShadowBlockElement> ShadowBlockElement::create(HTMLElement* shadowParent) { return adoptRef(new ShadowBlockElement(shadowParent)); } -ShadowBlockElement::ShadowBlockElement(Node* shadowParent) +ShadowBlockElement::ShadowBlockElement(HTMLElement* shadowParent) : ShadowElement<HTMLDivElement>(divTag, shadowParent) { } @@ -66,7 +66,7 @@ void ShadowBlockElement::updateStyleForPart(PseudoId pseudoId) renderer()->setStyle(createStyleForPart(renderer()->parent(), pseudoId)); } -PassRefPtr<ShadowBlockElement> ShadowBlockElement::createForPart(Node* shadowParent, PseudoId pseudoId) +PassRefPtr<ShadowBlockElement> ShadowBlockElement::createForPart(HTMLElement* shadowParent, PseudoId pseudoId) { RenderObject* parentRenderer = shadowParent->renderer(); RefPtr<RenderStyle> styleForPart = createStyleForPart(parentRenderer, pseudoId); @@ -103,12 +103,12 @@ bool ShadowBlockElement::partShouldHaveStyle(const RenderObject* parentRenderer, return !(pseudoStyle && pseudoStyle->hasAppearance()); } -PassRefPtr<ShadowInputElement> ShadowInputElement::create(Node* shadowParent) +PassRefPtr<ShadowInputElement> ShadowInputElement::create(HTMLElement* shadowParent) { return adoptRef(new ShadowInputElement(shadowParent)); } -ShadowInputElement::ShadowInputElement(Node* shadowParent) +ShadowInputElement::ShadowInputElement(HTMLElement* shadowParent) : ShadowElement<HTMLInputElement>(inputTag, shadowParent) { } diff --git a/WebCore/rendering/ShadowElement.h b/WebCore/rendering/ShadowElement.h index b8aacfd..04db62b 100644 --- a/WebCore/rendering/ShadowElement.h +++ b/WebCore/rendering/ShadowElement.h @@ -37,31 +37,31 @@ namespace WebCore { template<class BaseElement> class ShadowElement : public BaseElement { protected: - ShadowElement(const QualifiedName& name, Node* shadowParent) + ShadowElement(const QualifiedName& name, HTMLElement* shadowParent) : BaseElement(name, shadowParent->document()) , m_shadowParent(shadowParent) { } - Node* shadowParent() const { return m_shadowParent; } + HTMLElement* shadowParent() const { return m_shadowParent; } private: virtual bool isShadowNode() const { return true; } - virtual Node* shadowParentNode() { return m_shadowParent; } + virtual ContainerNode* shadowParentNode() { return m_shadowParent; } - Node* m_shadowParent; + HTMLElement* m_shadowParent; }; class ShadowBlockElement : public ShadowElement<HTMLDivElement> { public: - static PassRefPtr<ShadowBlockElement> create(Node*); - static PassRefPtr<ShadowBlockElement> createForPart(Node*, PseudoId); + static PassRefPtr<ShadowBlockElement> create(HTMLElement*); + static PassRefPtr<ShadowBlockElement> createForPart(HTMLElement*, PseudoId); static bool partShouldHaveStyle(const RenderObject* parentRenderer, PseudoId pseudoId); void layoutAsPart(const IntRect& partRect); void updateStyleForPart(PseudoId); protected: - ShadowBlockElement(Node*); + ShadowBlockElement(HTMLElement*); private: static PassRefPtr<RenderStyle> createStyleForPart(RenderObject*, PseudoId); @@ -69,9 +69,9 @@ private: class ShadowInputElement : public ShadowElement<HTMLInputElement> { public: - static PassRefPtr<ShadowInputElement> create(Node*); + static PassRefPtr<ShadowInputElement> create(HTMLElement*); protected: - ShadowInputElement(Node*); + ShadowInputElement(HTMLElement*); }; } // namespace WebCore diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index 9852aa6..1939133 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -39,6 +39,7 @@ #include "Page.h" #include "RenderLayer.h" #include "RenderTextControlSingleLine.h" +#include "ScrollbarTheme.h" #include "SpeechInput.h" namespace WebCore { @@ -84,13 +85,13 @@ VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& po // ---------------------------- -TextControlInnerElement::TextControlInnerElement(Document* document, Node* shadowParent) +TextControlInnerElement::TextControlInnerElement(Document* document, HTMLElement* shadowParent) : HTMLDivElement(divTag, document) , m_shadowParent(shadowParent) { } -PassRefPtr<TextControlInnerElement> TextControlInnerElement::create(Node* shadowParent) +PassRefPtr<TextControlInnerElement> TextControlInnerElement::create(HTMLElement* shadowParent) { return adoptRef(new TextControlInnerElement(shadowParent->document(), shadowParent)); } @@ -112,9 +113,12 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render setInDocument(); // For elements without a shadow parent, add the node to the DOM normally. - if (!m_shadowParent) - parent->legacyParserAddChild(this); - + if (!m_shadowParent) { + // FIXME: This code seems very wrong. Why are we magically adding |this| to the DOM here? + // We shouldn't be calling parser API methods outside of the parser! + parent->deprecatedParserAddChild(this); + } + // Add the renderer to the render tree if (renderer) parent->renderer()->addChild(renderer); @@ -122,12 +126,12 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render // ---------------------------- -inline TextControlInnerTextElement::TextControlInnerTextElement(Document* document, Node* shadowParent) +inline TextControlInnerTextElement::TextControlInnerTextElement(Document* document, HTMLElement* shadowParent) : TextControlInnerElement(document, shadowParent) { } -PassRefPtr<TextControlInnerTextElement> TextControlInnerTextElement::create(Document* document, Node* shadowParent) +PassRefPtr<TextControlInnerTextElement> TextControlInnerTextElement::create(Document* document, HTMLElement* shadowParent) { return adoptRef(new TextControlInnerTextElement(document, shadowParent)); } @@ -251,14 +255,16 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* event) // ---------------------------- -inline SpinButtonElement::SpinButtonElement(Node* shadowParent) +inline SpinButtonElement::SpinButtonElement(HTMLElement* shadowParent) : TextControlInnerElement(shadowParent->document(), shadowParent) , m_capturing(false) , m_upDownState(Indeterminate) + , m_pressStartingState(Indeterminate) + , m_repeatingTimer(this, &SpinButtonElement::repeatingTimerFired) { } -PassRefPtr<SpinButtonElement> SpinButtonElement::create(Node* shadowParent) +PassRefPtr<SpinButtonElement> SpinButtonElement::create(HTMLElement* shadowParent) { return adoptRef(new SpinButtonElement(shadowParent)); } @@ -271,13 +277,6 @@ void SpinButtonElement::defaultEventHandler(Event* event) return; } - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - if (mouseEvent->button() != LeftButton) { - if (!event->defaultHandled()) - HTMLDivElement::defaultEventHandler(event); - return; - } - RenderBox* box = renderBox(); if (!box) { if (!event->defaultHandled()) @@ -292,23 +291,24 @@ void SpinButtonElement::defaultEventHandler(Event* event) return; } + MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); - if (event->type() == eventNames().clickEvent) { + if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { if (box->borderBoxRect().contains(local)) { RefPtr<Node> protector(input); input->focus(); input->select(); - if (local.y() < box->height() / 2) - input->stepUpFromRenderer(1); - else - input->stepUpFromRenderer(-1); + input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1); event->setDefaultHandled(); + startRepeatingTimer(); } - } else if (event->type() == eventNames().mousemoveEvent) { + } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) + stopRepeatingTimer(); + else if (event->type() == eventNames().mousemoveEvent) { if (box->borderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document()->frame()) { - frame->eventHandler()->setCapturingMouseEventsNode(input); + frame->eventHandler()->setCapturingMouseEventsNode(this); m_capturing = true; } } @@ -318,6 +318,7 @@ void SpinButtonElement::defaultEventHandler(Event* event) renderer()->repaint(); } else { if (m_capturing) { + stopRepeatingTimer(); if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(0); m_capturing = false; @@ -330,6 +331,33 @@ void SpinButtonElement::defaultEventHandler(Event* event) HTMLDivElement::defaultEventHandler(event); } +void SpinButtonElement::startRepeatingTimer() +{ + m_pressStartingState = m_upDownState; + ScrollbarTheme* theme = ScrollbarTheme::nativeTheme(); + m_repeatingTimer.start(theme->initialAutoscrollTimerDelay(), theme->autoscrollTimerDelay()); +} + +void SpinButtonElement::stopRepeatingTimer() +{ + m_repeatingTimer.stop(); +} + +void SpinButtonElement::repeatingTimerFired(Timer<SpinButtonElement>*) +{ + HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); + if (input->disabled() || input->isReadOnlyFormControl()) + return; + // On Mac OS, NSStepper updates the value for the button under the mouse + // cursor regardless of the button pressed at the beginning. So the + // following check is not needed for Mac OS. +#if !OS(MAC_OS_X) + if (m_upDownState != m_pressStartingState) + return; +#endif + input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1); +} + void SpinButtonElement::setHovered(bool flag) { if (!hovered() && flag) @@ -342,7 +370,7 @@ void SpinButtonElement::setHovered(bool flag) #if ENABLE(INPUT_SPEECH) -inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Node* shadowParent) +inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(HTMLElement* shadowParent) : TextControlInnerElement(shadowParent->document(), shadowParent) , m_capturing(false) , m_state(Idle) @@ -360,7 +388,7 @@ InputFieldSpeechButtonElement::~InputFieldSpeechButtonElement() } } -PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(Node* shadowParent) +PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(HTMLElement* shadowParent) { return adoptRef(new InputFieldSpeechButtonElement(shadowParent)); } @@ -397,7 +425,7 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event) if (event->type() == eventNames().clickEvent) { switch (m_state) { case Idle: - if (speechInput()->startRecognition(m_listenerId)) + if (speechInput()->startRecognition(m_listenerId, input->renderer()->absoluteBoundingBoxRect())) setState(Recording); break; case Recording: @@ -455,6 +483,10 @@ void InputFieldSpeechButtonElement::detach() if (Frame* frame = document()->frame()) frame->eventHandler()->setCapturingMouseEventsNode(0); } + + if (m_state != Idle) + speechInput()->cancelRecognition(m_listenerId); + TextControlInnerElement::detach(); } diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index 3fbc9c8..c146a42 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -29,6 +29,7 @@ #include "HTMLDivElement.h" #include "SpeechInputListener.h" +#include "Timer.h" #include <wtf/Forward.h> namespace WebCore { @@ -37,30 +38,30 @@ class SpeechInput; class TextControlInnerElement : public HTMLDivElement { public: - static PassRefPtr<TextControlInnerElement> create(Node* shadowParent); + static PassRefPtr<TextControlInnerElement> create(HTMLElement* shadowParent); void attachInnerElement(Node*, PassRefPtr<RenderStyle>, RenderArena*); protected: - TextControlInnerElement(Document*, Node* shadowParent = 0); + TextControlInnerElement(Document*, HTMLElement* shadowParent = 0); private: virtual bool isMouseFocusable() const { return false; } virtual bool isShadowNode() const { return m_shadowParent; } - virtual Node* shadowParentNode() { return m_shadowParent; } - void setShadowParentNode(Node* node) { m_shadowParent = node; } + virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + void setShadowParentNode(HTMLElement* shadowParent) { m_shadowParent = shadowParent; } - Node* m_shadowParent; + HTMLElement* m_shadowParent; }; class TextControlInnerTextElement : public TextControlInnerElement { public: - static PassRefPtr<TextControlInnerTextElement> create(Document*, Node* shadowParent); + static PassRefPtr<TextControlInnerTextElement> create(Document*, HTMLElement* shadowParent); virtual void defaultEventHandler(Event*); private: - TextControlInnerTextElement(Document*, Node* shadowParent); + TextControlInnerTextElement(Document*, HTMLElement* shadowParent); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); }; @@ -96,21 +97,26 @@ public: Up, }; - static PassRefPtr<SpinButtonElement> create(Node*); + static PassRefPtr<SpinButtonElement> create(HTMLElement*); UpDownState upDownState() const { return m_upDownState; } private: - SpinButtonElement(Node*); + SpinButtonElement(HTMLElement*); virtual bool isSpinButtonElement() const { return true; } // FIXME: shadowAncestorNode() should be const. virtual bool isEnabledFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isEnabledFormControl(); } virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isReadOnlyFormControl(); } virtual void defaultEventHandler(Event*); + void startRepeatingTimer(); + void stopRepeatingTimer(); + void repeatingTimerFired(Timer<SpinButtonElement>*); virtual void setHovered(bool = true); bool m_capturing; UpDownState m_upDownState; + UpDownState m_pressStartingState; + Timer<SpinButtonElement> m_repeatingTimer; }; #if ENABLE(INPUT_SPEECH) @@ -125,7 +131,7 @@ public: Recognizing, }; - static PassRefPtr<InputFieldSpeechButtonElement> create(Node*); + static PassRefPtr<InputFieldSpeechButtonElement> create(HTMLElement*); virtual ~InputFieldSpeechButtonElement(); virtual void detach(); @@ -138,7 +144,7 @@ public: void setRecognitionResult(int, const String& result); private: - InputFieldSpeechButtonElement(Node*); + InputFieldSpeechButtonElement(HTMLElement*); SpeechInput* speechInput(); void setState(SpeechInputState state); diff --git a/WebCore/rendering/style/BindingURI.cpp b/WebCore/rendering/style/BindingURI.cpp deleted file mode 100644 index fd96de4..0000000 --- a/WebCore/rendering/style/BindingURI.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "BindingURI.h" - -#if ENABLE(XBL) - -namespace WebCore { - -BindingURI::BindingURI(StringImpl* uri) - : m_next(0) -{ - m_uri = uri; - if (uri) - uri->ref(); -} - -BindingURI::~BindingURI() -{ - if (m_uri) - m_uri->deref(); - delete m_next; -} - -BindingURI* BindingURI::copy() -{ - BindingURI* newBinding = new BindingURI(m_uri); - if (next()) { - BindingURI* nextCopy = next()->copy(); - newBinding->setNext(nextCopy); - } - - return newBinding; -} - -bool BindingURI::operator==(const BindingURI& o) const -{ - if ((m_next && !o.m_next) || (!m_next && o.m_next) || - (m_next && o.m_next && *m_next != *o.m_next)) - return false; - - if (m_uri == o.m_uri) - return true; - if (!m_uri || !o.m_uri) - return false; - - return String(m_uri) == String(o.m_uri); -} - -} // namespace WebCore - -#endif // ENABLE(XBL) diff --git a/WebCore/rendering/style/BindingURI.h b/WebCore/rendering/style/BindingURI.h deleted file mode 100644 index c844b1d..0000000 --- a/WebCore/rendering/style/BindingURI.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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) 2006 Graham Dennis (graham.dennis@gmail.com) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef BindingURI_h -#define BindingURI_h -#if ENABLE(XBL) - -#include <wtf/text/StringImpl.h> - -namespace WebCore { - -// This struct holds information about shadows for the text-shadow and box-shadow properties. - -struct BindingURI { - BindingURI(StringImpl*); - ~BindingURI(); - - BindingURI* copy(); - - bool operator==(const BindingURI& o) const; - bool operator!=(const BindingURI& o) const - { - return !(*this == o); - } - - BindingURI* next() { return m_next; } - void setNext(BindingURI* n) { m_next = n; } - - StringImpl* uri() { return m_uri; } - - BindingURI* m_next; - StringImpl* m_uri; -}; - -} // namespace WebCore - -#endif // ENABLE(XBL) -#endif // BindingURI_h diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 5a66c67..aaccbf7 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -699,20 +699,6 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& } } -#if ENABLE(XBL) -void RenderStyle::addBindingURI(StringImpl* uri) -{ - BindingURI* binding = new BindingURI(uri); - if (!bindingURIs()) - SET_VAR(rareNonInheritedData, bindingURI, binding) - else - for (BindingURI* b = bindingURIs(); b; b = b->next()) { - if (!b->next()) - b->setNext(binding); - } -} -#endif - void RenderStyle::setTextShadow(ShadowData* val, bool add) { ASSERT(!val || (!val->spread() && val->style() == Normal)); diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index df32d6b..1681890 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -87,10 +87,6 @@ #include "SVGRenderStyle.h" #endif -#if ENABLE(XBL) -#include "BindingURI.h" -#endif - #if COMPILER(WINSCW) #define compareEqual(t, u) ((t) == (u)) #else @@ -598,9 +594,6 @@ public: EPageBreak pageBreakAfter() const { return static_cast<EPageBreak>(noninherited_flags._page_break_after); } // CSS3 Getter Methods -#if ENABLE(XBL) - BindingURI* bindingURIs() const { return rareNonInheritedData->bindingURI; } -#endif int outlineOffset() const { @@ -963,12 +956,6 @@ public: void setPageBreakAfter(EPageBreak b) { noninherited_flags._page_break_after = b; } // CSS3 Setters -#if ENABLE(XBL) - void deleteBindingURIs() { SET_VAR(rareNonInheritedData, bindingURI, static_cast<BindingURI*>(0)); } - void inheritBindingURIs(BindingURI* other) { SET_VAR(rareNonInheritedData, bindingURI, other->copy()); } - void addBindingURI(StringImpl* uri); -#endif - void setOutlineOffset(int v) { SET_VAR(m_background, m_outline.m_offset, v) } void setTextShadow(ShadowData* val, bool add=false); void setTextStrokeColor(const Color& c) { SET_VAR(rareInheritedData, textStrokeColor, c) } diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp index 0df26f4..dc8a5af 100644 --- a/WebCore/rendering/style/SVGRenderStyle.cpp +++ b/WebCore/rendering/style/SVGRenderStyle.cpp @@ -178,6 +178,10 @@ StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const // NOTE: All comparisions below may only return StyleDifferenceRepaint + // Shadow changes need to cause repaints. + if (shadowSVG != other->shadowSVG) + return StyleDifferenceRepaint; + // Painting related properties only need repaints. if (miscNotEqual) { if (misc->floodColor != other->misc->floodColor diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/WebCore/rendering/style/StyleRareNonInheritedData.cpp index d5c9536..e293984 100644 --- a/WebCore/rendering/style/StyleRareNonInheritedData.cpp +++ b/WebCore/rendering/style/StyleRareNonInheritedData.cpp @@ -56,9 +56,6 @@ StyleRareNonInheritedData::StyleRareNonInheritedData() , m_perspective(RenderStyle::initialPerspective()) , m_perspectiveOriginX(RenderStyle::initialPerspectiveOriginX()) , m_perspectiveOriginY(RenderStyle::initialPerspectiveOriginY()) -#if ENABLE(XBL) - , bindingURI(0) -#endif , m_pageSize() , m_pageSizeType(PAGE_SIZE_AUTO) { @@ -97,9 +94,6 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited , m_perspective(o.m_perspective) , m_perspectiveOriginX(o.m_perspectiveOriginX) , m_perspectiveOriginY(o.m_perspectiveOriginY) -#if ENABLE(XBL) - , bindingURI(o.bindingURI ? o.bindingURI->copy() : 0) -#endif , m_pageSize(o.m_pageSize) , m_pageSizeType(o.m_pageSizeType) { @@ -109,18 +103,6 @@ StyleRareNonInheritedData::~StyleRareNonInheritedData() { } -#if ENABLE(XBL) -bool StyleRareNonInheritedData::bindingsEquivalent(const StyleRareNonInheritedData& o) const -{ - if (this == &o) return true; - if (!bindingURI && o.bindingURI || bindingURI && !o.bindingURI) - return false; - if (bindingURI && o.bindingURI && (*bindingURI != *o.bindingURI)) - return false; - return true; -} -#endif - bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) const { return lineClamp == o.lineClamp @@ -152,9 +134,6 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c && transitionDataEquivalent(o) && m_mask == o.m_mask && m_maskBoxImage == o.m_maskBoxImage -#if ENABLE(XBL) - && bindingsEquivalent(o) -#endif && (m_transformStyle3D == o.m_transformStyle3D) && (m_backfaceVisibility == o.m_backfaceVisibility) && (m_perspective == o.m_perspective) diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h index 1025d81..6003ea4 100644 --- a/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -54,10 +54,6 @@ struct LengthSize; struct StyleDashboardRegion; #endif -#if ENABLE(XBL) -class BindingURI; -#endif - // Page size type. // StyleRareNonInheritedData::m_pageSize is meaningful only when // StyleRareNonInheritedData::m_pageSizeType is PAGE_SIZE_RESOLVED. @@ -77,10 +73,6 @@ public: PassRefPtr<StyleRareNonInheritedData> copy() const { return adoptRef(new StyleRareNonInheritedData(*this)); } ~StyleRareNonInheritedData(); -#if ENABLE(XBL) - bool bindingsEquivalent(const StyleRareNonInheritedData&) const; -#endif - bool operator==(const StyleRareNonInheritedData&) const; bool operator!=(const StyleRareNonInheritedData& o) const { return !(*this == o); } @@ -137,10 +129,6 @@ public: LengthSize m_pageSize; PageSizeType m_pageSizeType; -#if ENABLE(XBL) - OwnPtr<BindingURI> bindingURI; // The XBL binding URI list. -#endif - private: StyleRareNonInheritedData(); StyleRareNonInheritedData(const StyleRareNonInheritedData&); |