diff options
Diffstat (limited to 'WebCore/rendering')
58 files changed, 993 insertions, 373 deletions
diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index b7e6de2..9f17b0c 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -808,7 +808,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 = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); + markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); // Optionally highlight the text @@ -837,7 +837,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 = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); + markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); } diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index eabb054..62e177d 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1687,6 +1687,16 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) return; } + // Check for page-break-inside: avoid, and it it's set, break and bail. + if (isPrinting && !childrenInline() && child->style()->pageBreakInside() == PBAVOID + && inRootBlockContext() + && ty + child->y() > paintInfo.rect.y() + && ty + child->y() < paintInfo.rect.bottom() + && ty + child->y() + child->height() > paintInfo.rect.bottom()) { + view()->setBestTruncatedAt(ty + child->y(), this, true); + return; + } + if (!child->hasSelfPaintingLayer() && !child->isFloating()) child->paint(info, tx, ty); @@ -1984,6 +1994,7 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) if (!hasLayer()) { FloatRect localBounds(gapRectsBounds); gapRectsBounds = localToContainerQuad(localBounds, layer->renderer()).enclosingBoundingBox(); + gapRectsBounds.move(layer->scrolledContentOffset()); } layer->addBlockSelectionGapsBounds(gapRectsBounds); } @@ -3897,6 +3908,31 @@ void RenderBlock::adjustRectForColumns(IntRect& r) const r = result; } +void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const +{ + if (!hasColumns()) + return; + + // FIXME: This is incorrect for right-to-left columns. + + Vector<IntRect>& columnRects = *this->columnRects(); + + int gapWidth = columnGap(); + int xOffset = 0; + int yOffset = 0; + size_t columnCount = columnRects.size(); + for (size_t i = 0; i < columnCount; ++i) { + IntRect columnRect = columnRects[i]; + if (point.y() < columnRect.bottom() + yOffset) { + offset.expand(xOffset, -yOffset); + return; + } + + xOffset += columnRect.width() + gapWidth; + yOffset += columnRect.height(); + } +} + void RenderBlock::calcPrefWidths() { ASSERT(prefWidthsDirty()); diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index d1d105a..c1f8dde 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -128,6 +128,7 @@ public: void clearTruncation(); void adjustRectForColumns(IntRect&) const; + virtual void adjustForColumns(IntSize&, const IntPoint&) const; void addContinuationWithOutline(RenderInline*); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 92c3d99..66a88e2 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -980,7 +980,7 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool } else fixed |= isFixedPos; - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint())); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -1021,7 +1021,7 @@ void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Transfor o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, IntPoint()); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -1032,7 +1032,7 @@ void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Transfor transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); } -IntSize RenderBox::offsetFromContainer(RenderObject* o) const +IntSize RenderBox::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); @@ -1041,14 +1041,9 @@ IntSize RenderBox::offsetFromContainer(RenderObject* o) const offset += relativePositionOffset(); if (!isInline() || isReplaced()) { - RenderBlock* cb; - if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition - && (cb = toRenderBlock(o))->hasColumns()) { - IntRect rect(x(), y(), 1, 1); - cb->adjustRectForColumns(rect); - offset.expand(rect.x(), rect.y()); - } else - offset.expand(x(), y()); + if (style()->position() != AbsolutePosition && style()->position() != FixedPosition) + o->adjustForColumns(offset, IntPoint(point.x() + x(), point.y() + y())); + offset.expand(x(), y()); } if (o->hasOverflowClip()) diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 401a46d..2ee368d 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -173,7 +173,7 @@ public: int overrideHeight() const; virtual void setOverrideSize(int); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; int calcBorderBoxWidth(int width) const; int calcBorderBoxHeight(int height) const; diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 59cbacf..a31442a 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -114,15 +114,27 @@ String RenderFileUploadControl::acceptTypes() return static_cast<HTMLInputElement*>(node())->accept(); } +void RenderFileUploadControl::iconForFiles(const Vector<String>& filenames) +{ + if (Chrome* chromePointer = chrome()) + chromePointer->iconForFiles(filenames, m_fileChooser); +} + void RenderFileUploadControl::click() { + if (Chrome* chromePointer = chrome()) + chromePointer->runOpenPanel(node()->document()->frame(), m_fileChooser); +} + +Chrome* RenderFileUploadControl::chrome() const +{ Frame* frame = node()->document()->frame(); if (!frame) - return; + return 0; Page* page = frame->page(); if (!page) - return; - page->chrome()->runOpenPanel(frame, m_fileChooser); + return 0; + return page->chrome(); } void RenderFileUploadControl::updateFromElement() diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h index dcdce4d..454041a 100644 --- a/WebCore/rendering/RenderFileUploadControl.h +++ b/WebCore/rendering/RenderFileUploadControl.h @@ -26,6 +26,7 @@ namespace WebCore { +class Chrome; class HTMLInputElement; // Each RenderFileUploadControl contains a RenderButton (for opening the file chooser), and @@ -41,16 +42,11 @@ public: void click(); - void valueChanged(); - void receiveDroppedFiles(const Vector<String>&); String buttonValue(); String fileTextValue() const; - bool allowsMultipleFiles(); - String acceptTypes(); - private: virtual const char* renderName() const { return "RenderFileUploadControl"; } @@ -60,6 +56,14 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + // FileChooserClient methods. + void valueChanged(); + void repaint() { RenderBlock::repaint(); } + bool allowsMultipleFiles(); + String acceptTypes(); + void iconForFiles(const Vector<String>&); + + Chrome* chrome() const; int maxFilenameWidth() const; PassRefPtr<RenderStyle> createButtonStyle(const RenderStyle* parentStyle) const; diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp index 5bb4439..aa28ff0 100644 --- a/WebCore/rendering/RenderForeignObject.cpp +++ b/WebCore/rendering/RenderForeignObject.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2009 Google, Inc. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,9 +28,9 @@ #include "GraphicsContext.h" #include "RenderView.h" #include "SVGForeignObjectElement.h" -#include "SVGLength.h" #include "SVGRenderSupport.h" -#include "SVGTransformList.h" +#include "SVGSVGElement.h" +#include "TransformState.h" namespace WebCore { @@ -38,22 +39,18 @@ RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node) { } -FloatPoint RenderForeignObject::translationForAttributes() const -{ - SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); - return FloatPoint(foreign->x().value(foreign), foreign->y().value(foreign)); -} - void RenderForeignObject::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled()) return; - // Copy the paint info so that modifications to the damage rect do not affect callers - PaintInfo childPaintInfo = paintInfo; + PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); - applyTransformToPaintInfo(childPaintInfo, localToParentTransform()); - childPaintInfo.context->clip(clipRect(0, 0)); + + applyTransformToPaintInfo(childPaintInfo, localTransform()); + + if (SVGRenderBase::isOverflowHidden(this)) + childPaintInfo.context->clip(m_viewport); float opacity = style()->opacity(); if (opacity < 1.0f) @@ -67,32 +64,33 @@ void RenderForeignObject::paint(PaintInfo& paintInfo, int, int) childPaintInfo.context->restore(); } -FloatRect RenderForeignObject::objectBoundingBox() const +IntRect RenderForeignObject::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { - return borderBoxRect(); + return SVGRenderBase::clippedOverflowRectForRepaint(this, repaintContainer); } -FloatRect RenderForeignObject::repaintRectInLocalCoordinates() const +void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed) { - // HACK: to maintain historical LayoutTest results for now. - // RenderForeignObject is a RenderBlock (not a RenderSVGModelObject) so this - // should not affect repaint correctness. But it should really be: - // return borderBoxRect(); - return FloatRect(); + SVGRenderBase::computeRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed) +const AffineTransform& RenderForeignObject::localToParentTransform() const { - rect = localToParentTransform().mapRect(rect); - style()->svgStyle()->inflateForShadow(rect); - RenderBlock::computeRectForRepaint(repaintContainer, rect, fixed); + m_localToParentTransform = localTransform(); + m_localToParentTransform.translate(m_viewport.x(), m_viewport.y()); + return m_localToParentTransform; } -const AffineTransform& RenderForeignObject::localToParentTransform() const +void RenderForeignObject::calcWidth() { - FloatPoint attributeTranslation(translationForAttributes()); - m_localToParentTransform = localTransform().translateRight(attributeTranslation.x(), attributeTranslation.y()); - return m_localToParentTransform; + // FIXME: Investigate in size rounding issues + setWidth(static_cast<int>(roundf(m_viewport.width()))); +} + +void RenderForeignObject::calcHeight() +{ + // FIXME: Investigate in size rounding issues + setHeight(static_cast<int>(roundf(m_viewport.height()))); } void RenderForeignObject::layout() @@ -101,18 +99,36 @@ void RenderForeignObject::layout() ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree. LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - m_localTransform = static_cast<SVGForeignObjectElement*>(node())->animatedLocalTransform(); + SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); + m_localTransform = foreign->animatedLocalTransform(); + + // Cache viewport boundaries + FloatPoint viewportLocation(foreign->x().value(foreign), foreign->y().value(foreign)); + m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(foreign), foreign->height().value(foreign))); + + // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct + // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those + // properties are ignored for non <svg> elements, so we mimic what happens when specifying them through CSS. + + // FIXME: Investigate in location rounding issues - only affects RenderForeignObject & RenderSVGText + setLocation(roundedIntPoint(viewportLocation)); RenderBlock::layout(); - repainter.repaintAfterLayout(); + repainter.repaintAfterLayout(); setNeedsLayout(false); } bool RenderForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { - FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); - return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localPoint.x()), static_cast<int>(localPoint.y()), 0, 0, hitTestAction); + FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent); + + // Early exit if local point is not contained in clipped viewport area + if (SVGRenderBase::isOverflowHidden(this) && !m_viewport.contains(localPoint)) + return false; + + IntPoint roundedLocalPoint = roundedIntPoint(localPoint); + return RenderBlock::nodeAtPoint(request, result, roundedLocalPoint.x(), roundedLocalPoint.y(), 0, 0, hitTestAction); } bool RenderForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) @@ -121,11 +137,14 @@ bool RenderForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int return false; } -void RenderForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const +void RenderForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const { + // When crawling up the hierachy starting from foreignObject child content, useTransforms may not be set to true. + if (!useTransforms) + useTransforms = true; SVGRenderBase::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState); } -} // namespace WebCore +} -#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) +#endif diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h index f32069c..bb6b555 100644 --- a/WebCore/rendering/RenderForeignObject.h +++ b/WebCore/rendering/RenderForeignObject.h @@ -21,8 +21,8 @@ #ifndef RenderForeignObject_h #define RenderForeignObject_h -#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) +#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) #include "AffineTransform.h" #include "FloatPoint.h" #include "RenderSVGBlock.h" @@ -39,15 +39,15 @@ public: virtual void paint(PaintInfo&, int parentX, int parentY); - virtual const AffineTransform& localToParentTransform() const; - + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + virtual bool requiresLayer() const { return false; } virtual void layout(); - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const { return borderBoxRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const { return m_viewport; } + virtual FloatRect strokeBoundingBox() const { return m_viewport; } + virtual FloatRect repaintRectInLocalCoordinates() const { return m_viewport; } virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); @@ -56,15 +56,18 @@ public: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const; private: - FloatPoint translationForAttributes() const; + virtual void calcWidth(); + virtual void calcHeight(); + virtual const AffineTransform& localToParentTransform() const; virtual AffineTransform localTransform() const { return m_localTransform; } + FloatRect m_viewport; AffineTransform m_localTransform; mutable AffineTransform m_localToParentTransform; }; -} // namespace WebCore +} -#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) -#endif // RenderForeignObject_h +#endif +#endif diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 9571751..d254835 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -710,7 +710,7 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, o->computeRectForRepaint(repaintContainer, rect, fixed); } -IntSize RenderInline::offsetFromContainer(RenderObject* container) const +IntSize RenderInline::offsetFromContainer(RenderObject* container, const IntPoint& point) const { ASSERT(container == this->container()); @@ -718,13 +718,7 @@ IntSize RenderInline::offsetFromContainer(RenderObject* container) const if (isRelPositioned()) offset += relativePositionOffset(); - if (!isInline() || isReplaced()) { - RenderBlock* cb; - if (container->isBlockFlow() && (cb = toRenderBlock(container))->hasColumns()) { - IntRect rect(0, 0, 1, 1); - cb->adjustRectForColumns(rect); - } - } + container->adjustForColumns(offset, point); if (container->hasOverflowClip()) offset -= toRenderBox(container)->layer()->scrolledContentOffset(); @@ -753,7 +747,7 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (!o) return; - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint())); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -785,7 +779,7 @@ void RenderInline::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Trans o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, IntPoint()); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index d35aa85..7fcb516 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -44,7 +44,7 @@ public: virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; IntRect linesBoundingBox() const; IntRect linesVisibleOverflowBoundingBox() const; diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 6dbb413..03a1e75 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -1227,7 +1227,9 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai #if USE(ACCELERATED_COMPOSITING) if (compositor()->inCompositingMode()) { - if (RenderLayer* compositingAncestor = ancestorCompositingLayer()) { + // Our stacking context is guaranteed to contain all of our descendants that may need + // repositioning, so update compositing layers from there. + if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { bool isUpdateRoot = true; compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot); } diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 3f60557..f637e3c 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -38,6 +38,7 @@ #include "GraphicsLayer.h" #include "HTMLCanvasElement.h" #include "HTMLElement.h" +#include "HTMLMediaElement.h" #include "HTMLNames.h" #include "InspectorTimelineAgent.h" #include "KeyframeList.h" @@ -215,9 +216,14 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() PluginWidget* pluginWidget = static_cast<PluginWidget*>(toRenderEmbeddedObject(renderer())->widget()); m_graphicsLayer->setContentsToMedia(pluginWidget->platformLayer()); } - +#if ENABLE(VIDEO) + else if (renderer()->isVideo()) { + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer()->node()); + m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer()); + } +#endif #if ENABLE(3D_CANVAS) - if (is3DCanvas(renderer())) { + else if (is3DCanvas(renderer())) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(canvas->renderingContext()); if (context->graphicsContext3D()->platformGraphicsContext3D()) diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 1d1e7c2..e70de96 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -69,6 +69,7 @@ #endif #if ENABLE(SVG) +#include "RenderSVGResource.h" #include "SVGRenderSupport.h" #endif @@ -1765,6 +1766,11 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (!o) return; + IntSize columnOffset; + o->adjustForColumns(columnOffset, roundedIntPoint(transformState.mappedPoint())); + if (!columnOffset.isZero()) + transformState.move(columnOffset); + if (o->hasOverflowClip()) transformState.move(-toRenderBox(o)->layer()->scrolledContentOffset()); @@ -1821,18 +1827,23 @@ void RenderObject::getTransformFromContainer(const RenderObject* containerObject FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderBoxModelObject* repaintContainer, bool fixed) const { - TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint(), &localQuad); + // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(), + // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks. + TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), &localQuad); mapLocalToContainer(repaintContainer, fixed, true, transformState); transformState.flatten(); return transformState.lastPlanarQuad(); } -IntSize RenderObject::offsetFromContainer(RenderObject* o) const +IntSize RenderObject::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); IntSize offset; + + o->adjustForColumns(offset, point); + if (o->hasOverflowClip()) offset -= toRenderBox(o)->layer()->scrolledContentOffset(); @@ -1842,6 +1853,7 @@ IntSize RenderObject::offsetFromContainer(RenderObject* o) const IntSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const { IntSize offset; + IntPoint referencePoint; const RenderObject* currContainer = this; do { RenderObject* nextContainer = currContainer->container(); @@ -1849,7 +1861,9 @@ IntSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const if (!nextContainer) break; ASSERT(!currContainer->hasTransform()); - offset += currContainer->offsetFromContainer(nextContainer); + IntSize currentOffset = currContainer->offsetFromContainer(nextContainer, referencePoint); + offset += currentOffset; + referencePoint.move(currentOffset); currContainer = nextContainer; } while (currContainer != container); @@ -2520,6 +2534,12 @@ const SVGRenderBase* RenderObject::toSVGRenderBase() const return 0; } +RenderSVGResource* RenderObject::toRenderSVGResource() +{ + ASSERT_NOT_REACHED(); + return 0; +} + FloatRect RenderObject::objectBoundingBox() const { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 6764818..791d4d0 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -54,6 +54,7 @@ class RenderTheme; class TransformState; class VisiblePosition; #if ENABLE(SVG) +class RenderSVGResource; class SVGRenderBase; #endif @@ -332,8 +333,10 @@ public: virtual bool isSVGText() const { return false; } virtual bool isSVGImage() const { return false; } virtual bool isSVGForeignObject() const { return false; } + virtual bool isSVGResource() const { return false; } virtual const SVGRenderBase* toSVGRenderBase() const; + virtual RenderSVGResource* toRenderSVGResource(); // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). @@ -562,8 +565,9 @@ public: // Convert a local quad into the coordinate system of container, taking transforms into account. FloatQuad localToContainerQuad(const FloatQuad&, RenderBoxModelObject* repaintContainer, bool fixed = false) const; - // Return the offset from the container() renderer (excluding transforms) - virtual IntSize offsetFromContainer(RenderObject*) const; + // Return the offset from the container() renderer (excluding transforms). In multi-column layout, + // different offsets apply at different points, so return the offset that applies to the given point. + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms. IntSize offsetFromAncestorContainer(RenderObject*) const; @@ -642,6 +646,10 @@ public: // that rect in the coordinate space of repaintContainer. virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + // If multiple-column layout results in applying an offset to the given point, add the same + // offset to the given size. + virtual void adjustForColumns(IntSize&, const IntPoint&) const { } + virtual unsigned int length() const { return 1; } bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); } diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index 7dbde42..bcedd38 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -34,9 +34,7 @@ #include "StrokeStyleApplier.h" #include "SVGPaintServer.h" #include "SVGRenderSupport.h" -#include "SVGResourceFilter.h" #include "SVGResourceMarker.h" -#include "SVGResourceMasker.h" #include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" #include "SVGURIReference.h" diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp index f13e2b4..4ab9d73 100644 --- a/WebCore/rendering/RenderRuby.cpp +++ b/WebCore/rendering/RenderRuby.cpp @@ -194,4 +194,4 @@ void RenderRubyAsBlock::removeChild(RenderObject* child) } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp index 65f9bc0..9b2dc9e 100644 --- a/WebCore/rendering/RenderRubyBase.cpp +++ b/WebCore/rendering/RenderRubyBase.cpp @@ -187,4 +187,4 @@ void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fr } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index 61be455..d91c625 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -225,4 +225,4 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyText.cpp b/WebCore/rendering/RenderRubyText.cpp index 1cf2b9e..12e8fea 100644 --- a/WebCore/rendering/RenderRubyText.cpp +++ b/WebCore/rendering/RenderRubyText.cpp @@ -51,4 +51,4 @@ bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderSVGBlock.cpp b/WebCore/rendering/RenderSVGBlock.cpp index f065c44..99725d6 100644 --- a/WebCore/rendering/RenderSVGBlock.cpp +++ b/WebCore/rendering/RenderSVGBlock.cpp @@ -1,8 +1,7 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2006 Apple Computer, Inc. - * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,9 +39,7 @@ void RenderSVGBlock::setStyle(PassRefPtr<RenderStyle> style) RefPtr<RenderStyle> useStyle = style; // SVG text layout code expects us to be a block-level style element. - if (useStyle->display() == NONE) - setChildrenInline(false); - else if (useStyle->isDisplayInlineType()) { + if (useStyle->isDisplayInlineType()) { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(useStyle.get()); newStyle->setDisplay(BLOCK); @@ -50,14 +47,27 @@ void RenderSVGBlock::setStyle(PassRefPtr<RenderStyle> style) } RenderBlock::setStyle(useStyle.release()); - setReplaced(false); +} + +void RenderSVGBlock::updateBoxModelInfoFromStyle() +{ + RenderBlock::updateBoxModelInfoFromStyle(); - //FIXME: Once overflow rules are supported by SVG we should - //probably map the CSS overflow rules rather than just ignoring - //them + // RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasOverflowClip(true). + // RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both + // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText. + // + // If we want to support overflow rules for <foreignObject> we can choose between two solutions: + // a) make RenderForeignObject require layers and SVG layer aware + // b) reactor overflow logic out of RenderLayer (as suggested by dhyatt), which is a large task + // + // Until this is resolved, disable overflow support. Opera/FF don't support it as well at the moment (Feb 2010). + // + // Note: This does NOT affect overflow handling on outer/inner <svg> elements - this is handled + // manually by RenderSVGRoot - which owns the documents enclosing root layer and thus works fine. setHasOverflowClip(false); } } -#endif // ENABLE(SVG) +#endif diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h index 0b0d107..19cac62 100644 --- a/WebCore/rendering/RenderSVGBlock.h +++ b/WebCore/rendering/RenderSVGBlock.h @@ -1,6 +1,4 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or @@ -22,8 +20,8 @@ #ifndef RenderSVGBlock_h #define RenderSVGBlock_h -#if ENABLE(SVG) +#if ENABLE(SVG) #include "RenderBlock.h" #include "SVGRenderSupport.h" @@ -39,8 +37,9 @@ public: private: virtual void setStyle(PassRefPtr<RenderStyle>); + virtual void updateBoxModelInfoFromStyle(); }; } -#endif // ENABLE(SVG) -#endif // !RenderSVGBlock_h +#endif +#endif diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 96eeaf9..6fb9501 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -37,9 +37,6 @@ #include "SVGLength.h" #include "SVGPreserveAspectRatio.h" #include "SVGRenderSupport.h" -#include "SVGResourceClipper.h" -#include "SVGResourceFilter.h" -#include "SVGResourceMasker.h" namespace WebCore { @@ -103,6 +100,12 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) paintInfo.context->restore(); } +void RenderSVGImage::destroy() +{ + SVGRenderBase::deregisterFromResources(this); + RenderImage::destroy(); +} + bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 8ed9146..f48b9dd 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -32,48 +32,50 @@ namespace WebCore { - class SVGImageElement; +class SVGImageElement; - class RenderSVGImage : public RenderImage, protected SVGRenderBase { - public: - RenderSVGImage(SVGImageElement*); +class RenderSVGImage : public RenderImage, protected SVGRenderBase { +public: + RenderSVGImage(SVGImageElement*); - private: - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - virtual const char* renderName() const { return "RenderSVGImage"; } - virtual bool isSVGImage() const { return true; } +private: + virtual const SVGRenderBase* toSVGRenderBase() const { return this; } + virtual const char* renderName() const { return "RenderSVGImage"; } + virtual bool isSVGImage() const { return true; } - virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const { return m_localBounds; } - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const; + virtual FloatRect strokeBoundingBox() const { return m_localBounds; } + virtual FloatRect repaintRectInLocalCoordinates() const; - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); - virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); + virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; - virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); - virtual void absoluteQuads(Vector<FloatQuad>&); - virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); + virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); + virtual void absoluteQuads(Vector<FloatQuad>&); + virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); - virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); - - virtual void layout(); - virtual void paint(PaintInfo&, int parentX, int parentY); + virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); + + virtual void layout(); + virtual void paint(PaintInfo&, int parentX, int parentY); - virtual bool requiresLayer() const { return false; } + virtual void destroy(); - virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); - virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); + virtual bool requiresLayer() const { return false; } - virtual AffineTransform localTransform() const { return m_localTransform; } + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); + virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); - AffineTransform m_localTransform; - FloatRect m_localBounds; - mutable FloatRect m_cachedLocalRepaintRect; - }; + virtual AffineTransform localTransform() const { return m_localTransform; } + + AffineTransform m_localTransform; + FloatRect m_localBounds; + mutable FloatRect m_cachedLocalRepaintRect; +}; } // namespace WebCore diff --git a/WebCore/rendering/RenderSVGInlineText.h b/WebCore/rendering/RenderSVGInlineText.h index e9c5d6e..b475067 100644 --- a/WebCore/rendering/RenderSVGInlineText.h +++ b/WebCore/rendering/RenderSVGInlineText.h @@ -39,6 +39,10 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle*); + // FIXME: We need objectBoundingBox for DRT results and filters at the moment. + // This should be fixed to give back the objectBoundingBox of the text root. + virtual FloatRect objectBoundingBox() const { return FloatRect(); } + virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp index 3fab5a6..c163dc6 100644 --- a/WebCore/rendering/RenderSVGModelObject.cpp +++ b/WebCore/rendering/RenderSVGModelObject.cpp @@ -38,10 +38,6 @@ #include "RenderView.h" #include "SVGStyledElement.h" -#if ENABLE(FILTERS) -#include "SVGResourceFilter.h" -#endif - namespace WebCore { RenderSVGModelObject::RenderSVGModelObject(SVGStyledElement* node) @@ -86,6 +82,12 @@ void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads) quads.append(absoluteClippedOverflowRect()); } +void RenderSVGModelObject::destroy() +{ + deregisterFromResources(this); + RenderObject::destroy(); +} + bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index 4c50734..c04c590 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -60,6 +60,8 @@ public: virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); + virtual void destroy(); + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; private: diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h new file mode 100644 index 0000000..38c6c09 --- /dev/null +++ b/WebCore/rendering/RenderSVGResource.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResource_h +#define RenderSVGResource_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "RenderSVGHiddenContainer.h" + +namespace WebCore { + +enum RenderSVGResourceType { + MaskerResourceType +}; + +class RenderSVGResource : public RenderSVGHiddenContainer { +public: + RenderSVGResource(SVGStyledElement* node) : RenderSVGHiddenContainer(node) { } + + template<class Renderer> + Renderer* cast() + { + if (Renderer::s_resourceType == resourceType()) + return static_cast<Renderer*>(this); + + return 0; + } + + virtual RenderSVGResource* toRenderSVGResource() { return this; } + virtual bool isSVGResource() const { return true; } + virtual bool drawsContents() { return false; } + + virtual void invalidateClients() = 0; + virtual void invalidateClient(RenderObject*) = 0; + + virtual bool applyResource(RenderObject*, GraphicsContext*) = 0; + virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0; + + virtual RenderSVGResourceType resourceType() const = 0; +}; + +template<typename Renderer> +Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id) +{ + if (id.isEmpty()) + return 0; + + Element* element = document->getElementById(id); + if (!element || !element->isSVGElement()) + return 0; + + RenderObject* renderer = element->renderer(); + if (!renderer) + return 0; + + RenderSVGResource* renderResource = renderer->toRenderSVGResource(); + if (!renderResource) + return 0; + + return renderResource->cast<Renderer>(); +} + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp new file mode 100644 index 0000000..2923c6e --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderSVGResourceMasker.h" + +#include "AffineTransform.h" +#include "CanvasPixelArray.h" +#include "Element.h" +#include "FloatPoint.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "ImageData.h" +#include "IntRect.h" +#include "SVGElement.h" +#include "SVGMaskElement.h" +#include "SVGStyledElement.h" +#include "SVGUnitTypes.h" +#include <wtf/Vector.h> + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType; + +RenderSVGResourceMasker::RenderSVGResourceMasker(SVGStyledElement* node) + : RenderSVGResource(node) +{ +} + +RenderSVGResourceMasker::~RenderSVGResourceMasker() +{ + deleteAllValues(m_masker); + m_masker.clear(); +} + +void RenderSVGResourceMasker::invalidateClients() +{ + HashMap<RenderObject*, MaskerData*>::const_iterator end = m_masker.end(); + for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) + it->first->setNeedsLayout(true); + deleteAllValues(m_masker); + m_masker.clear(); +} + +void RenderSVGResourceMasker::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_masker.contains(object)) + return; + + delete m_masker.take(object); +} + +bool RenderSVGResourceMasker::applyResource(RenderObject* object, GraphicsContext* context) +{ + ASSERT(object); + ASSERT(context); + + if (!m_masker.contains(object)) + m_masker.set(object, new MaskerData); + + MaskerData* maskerData = m_masker.get(object); + if (!maskerData->maskImage && !maskerData->emptyMask) { + SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); + if (!maskElement) + return false; + + createMaskImage(maskerData, maskElement, object); + } + + if (!maskerData->maskImage) + return false; + + context->clipToImageBuffer(maskerData->maskRect, maskerData->maskImage.get()); + return true; +} + +FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox) const +{ + if (SVGMaskElement* element = static_cast<SVGMaskElement*>(node())) + return element->maskBoundingBox(objectBoundingBox); + + return FloatRect(); +} + +void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) +{ + FloatRect objectBoundingBox = object->objectBoundingBox(); + + // Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present. + maskerData->maskRect = object->repaintRectInLocalCoordinates(); + if (maskerData->maskRect.isEmpty()) { + maskerData->emptyMask = true; + return; + } + + // Calculate the smallest rect for the mask ImageBuffer. + FloatRect repaintRect; + Vector<RenderObject*> rendererList; + for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) { + RenderObject* renderer = node->renderer(); + if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer) + continue; + + rendererList.append(renderer); + repaintRect.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates())); + } + + AffineTransform contextTransform; + // We need to scale repaintRect for objectBoundingBox to get the drawing area. + if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + FloatPoint contextAdjustment = repaintRect.location(); + repaintRect = contextTransform.mapRect(repaintRect); + repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y()); + contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y()); + } + repaintRect.intersect(maskerData->maskRect); + maskerData->maskRect = repaintRect; + IntRect maskImageRect = enclosingIntRect(maskerData->maskRect); + + maskImageRect.setLocation(IntPoint()); + + // Don't create ImageBuffers with image size of 0 + if (!maskImageRect.width() || !maskImageRect.height()) { + maskerData->emptyMask = true; + return; + } + + // FIXME: This changes color space to linearRGB, the default color space + // for masking operations in SVG. We need a switch for the other color-space + // attribute values sRGB, inherit and auto. + maskerData->maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB); + if (!maskerData->maskImage) + return; + + GraphicsContext* maskImageContext = maskerData->maskImage->context(); + ASSERT(maskImageContext); + + maskImageContext->save(); + + if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) + maskImageContext->translate(-maskerData->maskRect.x(), -maskerData->maskRect.y()); + maskImageContext->concatCTM(contextTransform); + + // draw the content into the ImageBuffer + Vector<RenderObject*>::iterator end = rendererList.end(); + for (Vector<RenderObject*>::iterator it = rendererList.begin(); it != end; it++) + renderSubtreeToImage(maskerData->maskImage.get(), *it); + + maskImageContext->restore(); + + // create the luminance mask + RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect)); + CanvasPixelArray* srcPixelArray(imageData->data()); + + for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) { + unsigned char a = srcPixelArray->get(pixelOffset + 3); + if (!a) + continue; + unsigned char r = srcPixelArray->get(pixelOffset); + unsigned char g = srcPixelArray->get(pixelOffset + 1); + unsigned char b = srcPixelArray->get(pixelOffset + 2); + + double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0); + srcPixelArray->set(pixelOffset + 3, luma); + } + + maskerData->maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint()); +} + +} diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h new file mode 100644 index 0000000..6c73c84 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResourceMasker_h +#define RenderSVGResourceMasker_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "IntSize.h" +#include "RenderSVGResource.h" +#include "SVGMaskElement.h" +#include "SVGUnitTypes.h" + +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +struct MaskerData { + MaskerData(FloatRect rect = FloatRect(), bool emptyObject = false) + : maskRect(rect) + , emptyMask(emptyObject) + { + } + + OwnPtr<ImageBuffer> maskImage; + FloatRect maskRect; + bool emptyMask; +}; + +class RenderSVGResourceMasker : public RenderSVGResource { + +public: + RenderSVGResourceMasker(SVGStyledElement*); + virtual ~RenderSVGResourceMasker(); + + virtual const char* renderName() const { return "RenderSVGResourceMasker"; } + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, GraphicsContext*); + virtual FloatRect resourceBoundingBox(const FloatRect&) const; + + SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); } + SVGUnitTypes::SVGUnitType maskContentUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskContentUnits()); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + +private: + void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*); + + HashMap<RenderObject*, MaskerData*> m_masker; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 74172fc..51bf3e7 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -77,6 +77,28 @@ void RenderSVGRoot::calcPrefWidths() setPrefWidthsDirty(false); } +int RenderSVGRoot::calcReplacedWidth(bool includeMaxWidth) const +{ + int replacedWidth = RenderBox::calcReplacedWidth(includeMaxWidth); + if (!style()->width().isPercent()) + return replacedWidth; + + // FIXME: Investigate in size rounding issues + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + return static_cast<int>(roundf(replacedWidth * svg->currentScale())); +} + +int RenderSVGRoot::calcReplacedHeight() const +{ + int replacedHeight = RenderBox::calcReplacedHeight(); + if (!style()->height().isPercent()) + return replacedHeight; + + // FIXME: Investigate in size rounding issues + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + return static_cast<int>(roundf(replacedHeight * svg->currentScale())); +} + void RenderSVGRoot::layout() { ASSERT(needsLayout()); @@ -84,22 +106,19 @@ void RenderSVGRoot::layout() // Arbitrary affine transforms are incompatible with LayoutState. view()->disableLayoutState(); - LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); + bool needsLayout = selfNeedsLayout(); + LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout); - int oldWidth = width(); + IntSize oldSize(width(), height()); calcWidth(); - - int oldHeight = height(); calcHeight(); - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); - setWidth(static_cast<int>(width() * svg->currentScale())); - setHeight(static_cast<int>(height() * svg->currentScale())); calcViewport(); // RenderSVGRoot needs to take special care to propagate window size changes to the children, // if the outermost <svg> is using relative x/y/width/height values. Hence the additonal parameters. - layoutChildren(this, selfNeedsLayout() || (svg->hasRelativeValues() && (width() != oldWidth || height() != oldHeight))); + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + layoutChildren(this, needsLayout || (svg->hasRelativeValues() && oldSize != size())); repainter.repaintAfterLayout(); view()->enableLayoutState(); @@ -123,7 +142,7 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) return; IntPoint parentOriginInContainer(parentX, parentY); - IntPoint borderBoxOriginInContainer = parentOriginInContainer + IntSize(x(), y()); + IntPoint borderBoxOriginInContainer = parentOriginInContainer + parentOriginToBorderBox(); if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y()); @@ -166,6 +185,12 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style()); } +void RenderSVGRoot::destroy() +{ + deregisterFromResources(this); + RenderBox::destroy(); +} + void RenderSVGRoot::calcViewport() { SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); @@ -177,15 +202,16 @@ void RenderSVGRoot::calcViewport() // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use // RenderBox::width()/height() (which pulls data from RenderStyle) m_viewportSize = FloatSize(width(), height()); - } else { - // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use - // the special relativeWidthValue accessors which respect the specified containerSize - SVGLength width = svg->width(); - SVGLength height = svg->height(); - float viewportWidth = (width.unitType() == LengthTypePercentage) ? svg->relativeWidthValue() : width.value(svg); - float viewportHeight = (height.unitType() == LengthTypePercentage) ? svg->relativeHeightValue() : height.value(svg); - m_viewportSize = FloatSize(viewportWidth, viewportHeight); + return; } + + // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use + // the special relativeWidthValue accessors which respect the specified containerSize + // FIXME: Check how SVGImage + zooming is supposed to be handled? + SVGLength width = svg->width(); + SVGLength height = svg->height(); + m_viewportSize = FloatSize(width.unitType() == LengthTypePercentage ? svg->relativeWidthValue() : width.value(svg), + height.unitType() == LengthTypePercentage ? svg->relativeHeightValue() : height.value(svg)); } // RenderBox methods will expect coordinates w/o any transforms in coordinates @@ -195,9 +221,9 @@ AffineTransform RenderSVGRoot::localToBorderBoxTransform() const IntSize borderAndPadding = borderOriginToContentBox(); SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); float scale = svg->currentScale(); - AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width(), borderAndPadding.height()); - ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y()); - return svg->viewBoxToViewTransform(width(), height()) * ctm; + FloatPoint translate = svg->currentTranslate(); + AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()); + return svg->viewBoxToViewTransform(width() / scale, height() / scale) * ctm; } IntSize RenderSVGRoot::parentOriginToBorderBox() const diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h index 8ad5e40..53c1298 100644 --- a/WebCore/rendering/RenderSVGRoot.h +++ b/WebCore/rendering/RenderSVGRoot.h @@ -50,10 +50,13 @@ private: virtual int lineHeight(bool b, bool isRootLineBox = false) const; virtual int baselinePosition(bool b, bool isRootLineBox = false) const; virtual void calcPrefWidths(); - + virtual int calcReplacedWidth(bool includeMaxWidth = true) const; + virtual int calcReplacedHeight() const; virtual void layout(); virtual void paint(PaintInfo&, int parentX, int parentY); + virtual void destroy(); + virtual const AffineTransform& localToParentTransform() const; bool fillContains(const FloatPoint&) const; diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index e332c85..b8b9553 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -108,6 +108,12 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul return false; } +void RenderSVGText::destroy() +{ + deregisterFromResources(this); + RenderSVGBlock::destroy(); +} + bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index 9ae96a0..ab4b09b 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -53,6 +53,8 @@ private: virtual bool requiresLayer() const { return false; } virtual void layout(); + virtual void destroy(); + virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 7398a2f..344f4ab 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -107,7 +107,7 @@ double SliderRange::clampValue(double value) double SliderRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) { double oldValue; - bool parseSuccess = HTMLInputElement::formStringToDouble(element->value(), &oldValue); + bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(element->value(), &oldValue); if (!parseSuccess) oldValue = (minimum + maximum) / 2; double newValue = clampValue(oldValue); @@ -383,7 +383,7 @@ void RenderSlider::updateFromElement() bool clamped; double value = range.valueFromElement(element, &clamped); if (clamped) - element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); + element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); // Layout will take care of the thumb's size and position. if (!m_thumb) { @@ -439,7 +439,7 @@ void RenderSlider::setValueForPosition(int position) if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); - element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); + element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); // Also update the position if appropriate. if (position != currentPosition()) { diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index d97ae6e..de71796 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -168,11 +168,11 @@ void RenderTableCell::setOverrideSize(int size) RenderBlock::setOverrideSize(size); } -IntSize RenderTableCell::offsetFromContainer(RenderObject* o) const +IntSize RenderTableCell::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); - IntSize offset = RenderBlock::offsetFromContainer(o); + IntSize offset = RenderBlock::offsetFromContainer(o, point); if (parent()) offset.expand(-parentBox()->x(), -parentBox()->y()); diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 0f8580d..a5a1edd 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -126,7 +126,7 @@ private: virtual void paintBoxDecorations(PaintInfo&, int tx, int ty); virtual void paintMask(PaintInfo&, int tx, int ty); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 2e696a9..4653273 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -230,27 +230,32 @@ void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u start = min(start, static_cast<unsigned>(INT_MAX)); end = min(end, static_cast<unsigned>(INT_MAX)); - FloatPoint absPos = localToAbsolute(FloatPoint()); - for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { - IntRect r = IntRect(absPos.x() + box->x(), absPos.y() + box->y(), box->width(), box->height()); + IntRect r = IntRect(box->x(), box->y(), box->width(), box->height()); if (useSelectionHeight) { - IntRect selectionRect = box->selectionRect(absPos.x(), absPos.y(), start, end); + IntRect selectionRect = box->selectionRect(0, 0, start, end); r.setHeight(selectionRect.height()); r.setY(selectionRect.y()); } + FloatPoint origin = localToAbsolute(r.location()); + r.setX(origin.x()); + r.setY(origin.y()); rects.append(r); } else { unsigned realEnd = min(box->end() + 1, end); - IntRect r = box->selectionRect(absPos.x(), absPos.y(), start, realEnd); + IntRect r = box->selectionRect(0, 0, start, realEnd); if (!r.isEmpty()) { if (!useSelectionHeight) { // change the height and y position because selectionRect uses selection-specific values r.setHeight(box->height()); - r.setY(absPos.y() + box->y()); + r.setY(box->y()); } + FloatPoint origin = localToAbsolute(r.location()); + localToAbsolute(origin); + r.setX(origin.x()); + r.setY(origin.y()); rects.append(r); } } diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index c0ba070..d18940b 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -459,6 +459,78 @@ IntRect RenderTextControl::controlClipRect(int tx, int ty) const return clipRect; } +static const char* fontFamiliesWithInvalidCharWidth[] = { + "American Typewriter", + "Arial Hebrew", + "Chalkboard", + "Cochin", + "Corsiva Hebrew", + "Courier", + "Euphemia UCAS", + "Geneva", + "Gill Sans", + "Hei", + "Helvetica", + "Hoefler Text", + "InaiMathi", + "Kai", + "Lucida Grande", + "Marker Felt", + "Monaco", + "Mshtakan", + "New Peninim MT", + "Osaka", + "Raanana", + "STHeiti", + "Symbol", + "Times", + "Apple Braille", + "Apple LiGothic", + "Apple LiSung", + "Apple Symbols", + "AppleGothic", + "AppleMyungjo", + "#GungSeo", + "#HeadLineA", + "#PCMyungjo", + "#PilGi", +}; + +// For font families where any of the fonts don't have a valid entry in the OS/2 table +// for avgCharWidth, fallback to the legacy webkit behavior of getting the avgCharWidth +// from the width of a '0'. This only seems to apply to a fixed number of Mac fonts, +// but, in order to get similar rendering across platforms, we do this check for +// all platforms. +bool RenderTextControl::hasValidAvgCharWidth(AtomicString family) +{ + static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0; + + if (!fontFamiliesWithInvalidCharWidthMap) { + fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>; + + for (unsigned i = 0; i < sizeof(fontFamiliesWithInvalidCharWidth) / sizeof(fontFamiliesWithInvalidCharWidth[0]); i++) + fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i])); + } + + return !fontFamiliesWithInvalidCharWidthMap->contains(family); +} + +float RenderTextControl::getAvgCharWidth(AtomicString family) +{ + if (hasValidAvgCharWidth(family)) + return roundf(style()->font().primaryFont()->avgCharWidth()); + + const UChar ch = '0'; + return style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false)); +} + +float RenderTextControl::scaleEmToUnits(int x) const +{ + // This matches the unitsPerEm value for MS Shell Dlg and Courier New from the "head" font table. + float unitsPerEm = 2048.0f; + return roundf(style()->font().size() * x / unitsPerEm); +} + void RenderTextControl::calcPrefWidths() { ASSERT(prefWidthsDirty()); @@ -470,8 +542,8 @@ void RenderTextControl::calcPrefWidths() m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value()); else { // Use average character width. Matches IE. - float charWidth = style()->font().primaryFont()->avgCharWidth(); - m_maxPrefWidth = preferredContentWidth(charWidth) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight(); + AtomicString family = style()->font().family().family(); + m_maxPrefWidth = preferredContentWidth(getAvgCharWidth(family)) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight(); } if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index d1f3749..2fc8edc 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -74,6 +74,10 @@ protected: int textBlockWidth() const; int textBlockHeight() const; + float scaleEmToUnits(int x) const; + + static bool hasValidAvgCharWidth(AtomicString family); + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const = 0; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight) = 0; virtual void cacheSelection(int start, int end) = 0; diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 0b4c7a7..9fbde3a 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -80,6 +80,17 @@ void RenderTextControlMultiLine::forwardEvent(Event* event) RenderTextControl::forwardEvent(event); } +float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family) +{ + // Since Lucida Grande is the default font, we want this to match the width + // of Courier New, the default font for textareas in IE, Firefox and Safari Win. + // 1229 is the avgCharWidth value in the OS/2 table for Courier New. + if (family == AtomicString("Lucida Grande")) + return scaleEmToUnits(1229); + + return RenderTextControl::getAvgCharWidth(family); +} + int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const { int factor = static_cast<HTMLTextAreaElement*>(node())->cols(); diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h index 3371a8f..fbca308 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.h +++ b/WebCore/rendering/RenderTextControlMultiLine.h @@ -40,6 +40,7 @@ private: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight); virtual int baselinePosition(bool firstLine, bool isRootLineBox) const; diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index b68f004..4edd203 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -385,7 +385,19 @@ int RenderTextControlSingleLine::textBlockWidth() const return width; } + +float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family) +{ + // Since Lucida Grande is the default font, we want this to match the width + // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and + // IE for some encodings (in IE, the default font is encoding specific). + // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg. + if (family == AtomicString("Lucida Grande")) + return scaleEmToUnits(901); + return RenderTextControl::getAvgCharWidth(family); +} + int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const { int factor = inputElement()->size(); @@ -394,8 +406,20 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const int result = static_cast<int>(ceilf(charWidth * factor)); + float maxCharWidth = 0.f; + AtomicString family = style()->font().family().family(); + // Since Lucida Grande is the default font, we want this to match the width + // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and + // IE for some encodings (in IE, the default font is encoding specific). + // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg. + if (family == AtomicString("Lucida Grande")) + maxCharWidth = scaleEmToUnits(4027); + else if (hasValidAvgCharWidth(family)) + maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth()); + // For text inputs, IE adds some extra width. - result += style()->font().primaryFont()->maxCharWidth() - charWidth; + if (maxCharWidth > 0.f) + result += maxCharWidth - charWidth; if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() + diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index e30ff0d..aa1f1e3 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -75,6 +75,7 @@ private: virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); int textBlockWidth() const; + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight); diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index e274b05..03aab1c 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -572,7 +572,7 @@ FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inpu const RenderObject* renderer = partRenderer; while (renderer && renderer != inputRenderer) { RenderObject* containingRenderer = renderer->container(); - offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); + offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint()); renderer = containingRenderer; } // If the input renderer was not a container, something went wrong diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index ddb538b..b6ce93d 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -520,7 +520,7 @@ FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRendere const RenderObject* renderer = partRenderer; while (renderer && renderer != inputRenderer) { RenderObject* containingRenderer = renderer->container(); - offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); + offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint()); renderer = containingRenderer; } // If the input renderer was not a container, something went wrong diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index ca4d9d1..164a656 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -395,6 +395,10 @@ void write(TextStream& ts, const RenderObject& o, int indent) write(ts, *toRenderPath(&o), indent); return; } + if (o.isSVGResource()) { + writeSVGResource(ts, o, indent); + return; + } if (o.isSVGContainer()) { writeSVGContainer(ts, o, indent); return; diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index 813f2ef..13d6f60 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -275,14 +275,6 @@ void RenderVideo::acceleratedRenderingStateChanged() if (p) p->acceleratedRenderingStateChanged(); } - -GraphicsLayer* RenderVideo::videoGraphicsLayer() const -{ - if (hasLayer() && layer()->isComposited()) - return layer()->backing()->graphicsLayer(); - - return 0; -} #endif // USE(ACCELERATED_COMPOSITING) } // namespace WebCore diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h index 3ca5328..16c846d 100644 --- a/WebCore/rendering/RenderVideo.h +++ b/WebCore/rendering/RenderVideo.h @@ -34,9 +34,6 @@ namespace WebCore { class HTMLMediaElement; class HTMLVideoElement; -#if USE(ACCELERATED_COMPOSITING) -class GraphicsLayer; -#endif class RenderVideo : public RenderMedia { public: @@ -49,7 +46,6 @@ public: #if USE(ACCELERATED_COMPOSITING) bool supportsAcceleratedRendering() const; void acceleratedRenderingStateChanged(); - GraphicsLayer* videoGraphicsLayer() const; #endif private: diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h index f80c79c..f0d1fa4 100644 --- a/WebCore/rendering/SVGCharacterLayoutInfo.h +++ b/WebCore/rendering/SVGCharacterLayoutInfo.h @@ -297,13 +297,6 @@ struct SVGTextChunkWalkerBase { // Followings methods are only used for painting text chunks virtual void start(InlineBox*) = 0; virtual void end(InlineBox*) = 0; - - virtual bool setupBackground(InlineBox*) = 0; - virtual bool setupFill(InlineBox*) = 0; - virtual bool setupFillSelection(InlineBox*) = 0; - virtual bool setupStroke(InlineBox*) = 0; - virtual bool setupStrokeSelection(InlineBox*) = 0; - virtual bool setupForeground(InlineBox*) = 0; }; template<typename CallbackClass> @@ -319,31 +312,14 @@ public: typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box); typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupBackgroundCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupForegroundCallback)(InlineBox* box); - - SVGTextChunkWalker(CallbackClass* object, + SVGTextChunkWalker(CallbackClass* object, SVGTextChunkWalkerCallback walker, SVGTextChunkStartCallback start = 0, - SVGTextChunkEndCallback end = 0, - SVGTextChunkSetupBackgroundCallback background = 0, - SVGTextChunkSetupFillCallback fill = 0, - SVGTextChunkSetupFillCallback fillSelection = 0, - SVGTextChunkSetupStrokeCallback stroke = 0, - SVGTextChunkSetupStrokeCallback strokeSelection = 0, - SVGTextChunkSetupForegroundCallback foreground = 0) + SVGTextChunkEndCallback end = 0) : m_object(object) , m_walkerCallback(walker) , m_startCallback(start) , m_endCallback(end) - , m_setupBackgroundCallback(background) - , m_setupFillCallback(fill) - , m_setupFillSelectionCallback(fillSelection) - , m_setupStrokeCallback(stroke) - , m_setupStrokeSelectionCallback(strokeSelection) - , m_setupForegroundCallback(foreground) { ASSERT(object); ASSERT(walker); @@ -372,71 +348,11 @@ public: ASSERT_NOT_REACHED(); } - virtual bool setupBackground(InlineBox* box) - { - if (m_setupBackgroundCallback) - return (*m_object.*m_setupBackgroundCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupFill(InlineBox* box) - { - if (m_setupFillCallback) - return (*m_object.*m_setupFillCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupFillSelection(InlineBox* box) - { - if (m_setupFillSelectionCallback) - return (*m_object.*m_setupFillSelectionCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupStroke(InlineBox* box) - { - if (m_setupStrokeCallback) - return (*m_object.*m_setupStrokeCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupStrokeSelection(InlineBox* box) - { - if (m_setupStrokeSelectionCallback) - return (*m_object.*m_setupStrokeSelectionCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupForeground(InlineBox* box) - { - if (m_setupForegroundCallback) - return (*m_object.*m_setupForegroundCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - private: CallbackClass* m_object; SVGTextChunkWalkerCallback m_walkerCallback; SVGTextChunkStartCallback m_startCallback; SVGTextChunkEndCallback m_endCallback; - SVGTextChunkSetupBackgroundCallback m_setupBackgroundCallback; - SVGTextChunkSetupFillCallback m_setupFillCallback; - SVGTextChunkSetupFillCallback m_setupFillSelectionCallback; - SVGTextChunkSetupStrokeCallback m_setupStrokeCallback; - SVGTextChunkSetupStrokeCallback m_setupStrokeSelectionCallback; - SVGTextChunkSetupForegroundCallback m_setupForegroundCallback; }; struct SVGTextChunkLayoutInfo { diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 079a36e..dc1b3c1 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -28,13 +28,15 @@ #include "SVGRenderSupport.h" #include "AffineTransform.h" +#include "Document.h" #include "ImageBuffer.h" #include "RenderObject.h" #include "RenderSVGContainer.h" +#include "RenderSVGResource.h" +#include "RenderSVGResourceMasker.h" #include "RenderView.h" #include "SVGResourceClipper.h" #include "SVGResourceFilter.h" -#include "SVGResourceMasker.h" #include "SVGStyledElement.h" #include "SVGURIReference.h" #include "TransformState.h" @@ -127,17 +129,14 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject filter = newFilter; #endif - SVGResourceClipper* clipper = getClipperById(document, clipperId, object); - SVGResourceMasker* masker = getMaskerById(document, maskerId, object); - - if (masker) { - masker->addClient(styledElement); - if (!masker->applyMask(paintInfo.context, object)) + // apply Masker + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { + if (!masker->applyResource(object, paintInfo.context)) return false; } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); - if (clipper) { + if (SVGResourceClipper* clipper = getClipperById(document, clipperId, object)) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, object->objectBoundingBox()); } else if (!clipperId.isEmpty()) @@ -297,13 +296,19 @@ FloatRect SVGRenderBase::clipperBoundingBoxForRenderer(const RenderObject* objec FloatRect SVGRenderBase::maskerBoundingBoxForRenderer(const RenderObject* object) const { - SVGResourceMasker* masker = getMaskerById(object->document(), object->style()->svgStyle()->maskElement(), object); - if (masker) - return masker->maskerBoundingBox(object->objectBoundingBox()); + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) + return masker->resourceBoundingBox(object->objectBoundingBox()); return FloatRect(); } +void SVGRenderBase::deregisterFromResources(RenderObject* object) +{ + // We only have a renderer for masker at the moment. + if (RenderSVGResourceMasker* resource = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) + resource->invalidateClient(object); +} + void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineTransform& localToAncestorTransform) { if (localToAncestorTransform.isIdentity()) diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index cf75365..427ff1f 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -26,61 +26,65 @@ #if ENABLE(SVG) #include "RenderObject.h" +#include "SVGElement.h" +#include "SVGStyledElement.h" namespace WebCore { - class SVGResourceFilter; - class ImageBuffer; +class SVGResourceFilter; +class ImageBuffer; - // SVGRendererBase is an abstract base class which all SVG renderers inherit - // from in order to share SVG renderer code. - // FIXME: This code can all move into RenderSVGModelObject once - // all SVG renderers inherit from RenderSVGModelObject. - class SVGRenderBase { - public: - virtual ~SVGRenderBase(); +// SVGRendererBase is an abstract base class which all SVG renderers inherit +// from in order to share SVG renderer code. +// FIXME: This code can all move into RenderSVGModelObject once +// all SVG renderers inherit from RenderSVGModelObject. +class SVGRenderBase { +public: + virtual ~SVGRenderBase(); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } + virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - // FIXME: These are only public for SVGRootInlineBox. - // It's unclear if these should be exposed or not. SVGRootInlineBox may - // pass the wrong RenderObject* and boundingBox to these functions. - static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0); - static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext); + // FIXME: These are only public for SVGRootInlineBox. + // It's unclear if these should be exposed or not. SVGRootInlineBox may + // pass the wrong RenderObject* and boundingBox to these functions. + static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0); + static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext); - // Layout all children of the passed render object - static void layoutChildren(RenderObject*, bool selfNeedsLayout); + // Layout all children of the passed render object + static void layoutChildren(RenderObject*, bool selfNeedsLayout); - // Helper function determining wheter overflow is hidden - static bool isOverflowHidden(const RenderObject*); + // Helper function determining wheter overflow is hidden + static bool isOverflowHidden(const RenderObject*); - virtual FloatRect strokeBoundingBox() const { return FloatRect(); } - virtual FloatRect markerBoundingBox() const { return FloatRect(); } + virtual FloatRect strokeBoundingBox() const { return FloatRect(); } + virtual FloatRect markerBoundingBox() const { return FloatRect(); } - // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates - FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; - FloatRect clipperBoundingBoxForRenderer(const RenderObject*) const; - FloatRect maskerBoundingBoxForRenderer(const RenderObject*) const; + // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates + FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; + FloatRect clipperBoundingBoxForRenderer(const RenderObject*) const; + FloatRect maskerBoundingBoxForRenderer(const RenderObject*) const; - protected: - static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); - static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed); +protected: + static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); + static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed); - static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&); + static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&); - // Used to share the "walk all the children" logic between objectBoundingBox - // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer - static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent); - }; + // Used to share the "walk all the children" logic between objectBoundingBox + // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer + static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent); - // FIXME: This should move to RenderObject or PaintInfo - // Used for transforming the GraphicsContext and damage rect before passing PaintInfo to child renderers. - void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& localToChildTransform); + static void deregisterFromResources(RenderObject*); +}; - // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. - void renderSubtreeToImage(ImageBuffer*, RenderObject*); +// FIXME: This should move to RenderObject or PaintInfo +// Used for transforming the GraphicsContext and damage rect before passing PaintInfo to child renderers. +void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& localToChildTransform); - void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); +// This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. +void renderSubtreeToImage(ImageBuffer*, RenderObject*); + +void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index aff718f..f892144 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -38,6 +38,7 @@ #include "RenderPath.h" #include "RenderSVGContainer.h" #include "RenderSVGInlineText.h" +#include "RenderSVGResourceMasker.h" #include "RenderSVGRoot.h" #include "RenderSVGText.h" #include "RenderTreeAsText.h" @@ -195,6 +196,23 @@ TextStream& operator<<(TextStream& ts, const AffineTransform& transform) return ts; } +static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType) +{ + switch (unitType) { + case SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN: + ts << "unknown"; + break; + case SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE: + ts << "userSpaceOnUse"; + break; + case SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: + ts << "objectBoundingBox"; + break; + } + + return ts; +} + TextStream& operator<<(TextStream& ts, const Color& c) { return ts << c.name(); @@ -464,11 +482,33 @@ static void writeChildren(TextStream& ts, const RenderObject& object, int indent write(ts, *child, indent + 1); } +void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) +{ + writeStandardPrefix(ts, object, indent); + + Element* element = static_cast<Element*>(object.node()); + const AtomicString& id = element->getIDAttribute(); + writeNameAndQuotedValue(ts, "id", id); + + RenderSVGResource* resource = const_cast<RenderObject&>(object).toRenderSVGResource(); + if (resource->resourceType() == MaskerResourceType) { + RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); + ASSERT(masker); + writeNameValuePair(ts, "maskUnits", masker->maskUnits()); + writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); + } + + // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. + ts << "\n"; + writeChildren(ts, object, indent); +} + void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent) { writeStandardPrefix(ts, container, indent); writePositionAndStyle(ts, container); ts << "\n"; + writeResources(ts, container, indent); writeChildren(ts, container, indent); } @@ -484,6 +524,7 @@ void writeSVGText(TextStream& ts, const RenderBlock& text, int indent) writeStandardPrefix(ts, text, indent); writeRenderSVGTextBox(ts, text); ts << "\n"; + writeResources(ts, text, indent); writeChildren(ts, text, indent); } @@ -493,20 +534,41 @@ void writeSVGInlineText(TextStream& ts, const RenderText& text, int indent) // Why not just linesBoundingBox()? ts << " " << FloatRect(text.firstRunOrigin(), text.linesBoundingBox().size()) << "\n"; + writeResources(ts, text, indent); writeSVGInlineTextBoxes(ts, text, indent); } +void writeSVGImage(TextStream& ts, const RenderImage& image, int indent) +{ + writeStandardPrefix(ts, image, indent); + writePositionAndStyle(ts, image); + ts << "\n"; + writeResources(ts, image, indent); +} + void write(TextStream& ts, const RenderPath& path, int indent) { writeStandardPrefix(ts, path, indent); ts << path << "\n"; + writeResources(ts, path, indent); } -void writeSVGImage(TextStream& ts, const RenderImage& image, int indent) +void writeResources(TextStream& ts, const RenderObject& object, int indent) { - writeStandardPrefix(ts, image, indent); - writePositionAndStyle(ts, image); - ts << "\n"; + const RenderStyle* style = object.style(); + const SVGRenderStyle* svgStyle = style->svgStyle(); + + if (!svgStyle->maskElement().isEmpty()) { + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskElement())) { + writeIndent(ts, indent); + ts << " "; + writeNameAndQuotedValue(ts, "masker", svgStyle->maskElement()); + ts << " "; + writeStandardPrefix(ts, *masker, 0); + ts << " " << masker->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + } + } + // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. } void writeRenderResources(TextStream& ts, Node* parent) diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h index 13fc475..905652b 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.h +++ b/WebCore/rendering/SVGRenderTreeAsText.h @@ -46,14 +46,17 @@ namespace WebCore { class RenderSVGRoot; class RenderText; class AffineTransform; + class SVGUnitTypes; // functions used by the main RenderTreeAsText code void write(TextStream&, const RenderPath&, int indent); void write(TextStream&, const RenderSVGRoot&, int indent); +void writeSVGResource(TextStream&, const RenderObject&, int indent); void writeSVGContainer(TextStream&, const RenderObject&, int indent); void writeSVGImage(TextStream&, const RenderImage&, int indent); void writeSVGInlineText(TextStream&, const RenderText&, int indent); void writeSVGText(TextStream&, const RenderBlock&, int indent); +void writeResources(TextStream&, const RenderObject&, int indent); void writeRenderResources(TextStream&, Node* parent); diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index d0dd4a8..03b9db4 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -363,10 +363,10 @@ struct SVGRootInlineBoxPaintWalker { ASSERT(!m_chunkStarted); } - bool mayHaveSelection(InlineBox* box) const + bool mayHaveSelection(SVGInlineTextBox* box) const { int selectionStart = 0, selectionEnd = 0; - box->renderer()->selectionStartEnd(selectionStart, selectionEnd); + box->selectionStartEnd(selectionStart, selectionEnd); return selectionStart < selectionEnd; } @@ -436,13 +436,13 @@ struct SVGRootInlineBoxPaintWalker { m_paintInfo.rect = m_savedInfo.rect; } - bool chunkSetupBackgroundCallback(InlineBox* /*box*/) + bool setupBackground(SVGInlineTextBox* /*box*/) { m_textPaintInfo.subphase = SVGTextPaintSubphaseBackground; return true; } - bool chunkSetupFillCallback(InlineBox* box) + bool setupFill(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -464,7 +464,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupFillSelectionCallback(InlineBox* box) + bool setupFillSelection(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -492,7 +492,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupStrokeCallback(InlineBox* box) + bool setupStroke(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -516,7 +516,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupStrokeSelectionCallback(InlineBox* box) + bool setupStrokeSelection(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -545,7 +545,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupForegroundCallback(InlineBox* /*box*/) + bool setupForeground(SVGInlineTextBox* /*box*/) { teardownFillPaintServer(); teardownStrokePaintServer(); @@ -576,6 +576,28 @@ struct SVGRootInlineBoxPaintWalker { void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) { + if (setupBackground(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupFill(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupFillSelection(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupStroke(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupStrokeSelection(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupForeground(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + } + + void paintChunk(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, + const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) + { RenderText* text = textBox->textRenderer(); ASSERT(text); @@ -679,13 +701,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) SVGTextChunkWalker<SVGRootInlineBoxPaintWalker> walker(&walkerCallback, &SVGRootInlineBoxPaintWalker::chunkPortionCallback, &SVGRootInlineBoxPaintWalker::chunkStartCallback, - &SVGRootInlineBoxPaintWalker::chunkEndCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupBackgroundCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupFillCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupFillSelectionCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupStrokeCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupStrokeSelectionCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupForegroundCallback); + &SVGRootInlineBoxPaintWalker::chunkEndCallback); walkTextChunks(&walker); } @@ -1777,28 +1793,7 @@ void SVGRootInlineBox::walkTextChunks(SVGTextChunkWalkerBase* walker, const SVGI ASSERT(itCharEnd <= curChunk.end); // Process this chunk portion - if (textBox) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - else { - if (walker->setupBackground(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupFill(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupFillSelection(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupStroke(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupStrokeSelection(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupForeground(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - } + (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); chunkOffset += length; diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 0952557..712344f 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -192,6 +192,11 @@ static inline int pseudoBit(PseudoId pseudo) return 1 << (pseudo - 1); } +bool RenderStyle::hasAnyPublicPseudoStyles() const +{ + return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits; +} + bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const { ASSERT(pseudo > NOPSEUDO); diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 696a2b7..c7db254 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -350,6 +350,7 @@ public: bool isStyleAvailable() const; + bool hasAnyPublicPseudoStyles() const; bool hasPseudoStyle(PseudoId pseudo) const; void setHasPseudoStyle(PseudoId pseudo); diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index 01862f6..4abbc1c 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -66,6 +66,7 @@ enum StyleDifferenceContextSensitiveProperty { // Static pseudo styles. Dynamic ones are produced on the fly. enum PseudoId { + // The order must be NOP ID, public IDs, and then internal IDs. NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER, SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL, MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER, @@ -75,7 +76,9 @@ enum PseudoId { MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, - FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON + FIRST_PUBLIC_PSEUDOID = FIRST_LINE, + FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON, + PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1) }; // These have been defined in the order of their precedence for border-collapsing. Do |