summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering')
-rw-r--r--WebCore/rendering/HitTestResult.cpp4
-rw-r--r--WebCore/rendering/InlineTextBox.cpp8
-rw-r--r--WebCore/rendering/MediaControlElements.cpp8
-rw-r--r--WebCore/rendering/MediaControlElements.h2
-rw-r--r--WebCore/rendering/PaintInfo.h6
-rw-r--r--WebCore/rendering/RenderBlock.cpp4
-rw-r--r--WebCore/rendering/RenderCounter.cpp5
-rw-r--r--WebCore/rendering/RenderLayer.cpp6
-rw-r--r--WebCore/rendering/RenderLayer.h2
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp2
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp28
-rw-r--r--WebCore/rendering/RenderLayerCompositor.h10
-rw-r--r--WebCore/rendering/RenderListMarker.cpp131
-rw-r--r--WebCore/rendering/RenderMeter.cpp4
-rw-r--r--WebCore/rendering/RenderObject.cpp5
-rw-r--r--WebCore/rendering/RenderPath.cpp56
-rw-r--r--WebCore/rendering/RenderPath.h1
-rw-r--r--WebCore/rendering/RenderProgress.cpp2
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.cpp74
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.h2
-rw-r--r--WebCore/rendering/RenderSVGResourceContainer.cpp2
-rw-r--r--WebCore/rendering/RenderSVGResourceGradient.cpp36
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.cpp48
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.h2
-rw-r--r--WebCore/rendering/RenderSVGResourcePattern.cpp232
-rw-r--r--WebCore/rendering/RenderSVGResourcePattern.h9
-rw-r--r--WebCore/rendering/RenderSlider.cpp12
-rw-r--r--WebCore/rendering/RenderTextControl.cpp2
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.cpp12
-rw-r--r--WebCore/rendering/RenderView.h17
-rw-r--r--WebCore/rendering/SVGImageBufferTools.cpp102
-rw-r--r--WebCore/rendering/SVGImageBufferTools.h10
-rw-r--r--WebCore/rendering/SVGInlineTextBox.cpp4
-rw-r--r--WebCore/rendering/SVGRenderSupport.cpp42
-rw-r--r--WebCore/rendering/SVGRenderSupport.h5
-rw-r--r--WebCore/rendering/SVGShadowTreeElements.cpp2
-rw-r--r--WebCore/rendering/SVGShadowTreeElements.h6
-rw-r--r--WebCore/rendering/ShadowElement.cpp10
-rw-r--r--WebCore/rendering/ShadowElement.h18
-rw-r--r--WebCore/rendering/TextControlInnerElements.cpp84
-rw-r--r--WebCore/rendering/TextControlInnerElements.h28
-rw-r--r--WebCore/rendering/style/BindingURI.cpp71
-rw-r--r--WebCore/rendering/style/BindingURI.h59
-rw-r--r--WebCore/rendering/style/RenderStyle.cpp14
-rw-r--r--WebCore/rendering/style/RenderStyle.h13
-rw-r--r--WebCore/rendering/style/SVGRenderStyle.cpp4
-rw-r--r--WebCore/rendering/style/StyleRareNonInheritedData.cpp21
-rw-r--r--WebCore/rendering/style/StyleRareNonInheritedData.h12
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&);