Index: Source/core/rendering/RenderObject.cpp |
diff --git a/Source/core/rendering/RenderObject.cpp b/Source/core/rendering/RenderObject.cpp |
index 4a385c0510141c1153eab7c5d86cd15e952860c8..96a28d4392bcdb5cd41f7d77e5274e5d91ee2bc2 100644 |
--- a/Source/core/rendering/RenderObject.cpp |
+++ b/Source/core/rendering/RenderObject.cpp |
@@ -41,6 +41,8 @@ |
#include "core/frame/EventHandlerRegistry.h" |
#include "core/frame/FrameView.h" |
#include "core/frame/LocalFrame.h" |
+#include "core/frame/Settings.h" |
+#include "core/frame/UseCounter.h" |
#include "core/html/HTMLAnchorElement.h" |
#include "core/html/HTMLElement.h" |
#include "core/html/HTMLHtmlElement.h" |
@@ -49,8 +51,7 @@ |
#include "core/page/AutoscrollController.h" |
#include "core/page/EventHandler.h" |
#include "core/page/Page.h" |
-#include "core/frame/Settings.h" |
-#include "core/frame/UseCounter.h" |
+#include "core/paint/ObjectPainter.h" |
#include "core/rendering/FlowThreadController.h" |
#include "core/rendering/HitTestResult.h" |
#include "core/rendering/RenderCounter.h" |
@@ -977,336 +978,9 @@ bool RenderObject::mustInvalidateBackgroundOrBorderPaintOnHeightChange() const |
return false; |
} |
-void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, |
- BoxSide side, Color color, EBorderStyle style, |
- int adjacentWidth1, int adjacentWidth2, bool antialias) |
-{ |
- int thickness; |
- int length; |
- if (side == BSTop || side == BSBottom) { |
- thickness = y2 - y1; |
- length = x2 - x1; |
- } else { |
- thickness = x2 - x1; |
- length = y2 - y1; |
- } |
- |
- // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However |
- // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions. |
- if (!thickness || !length) |
- return; |
- |
- if (style == DOUBLE && thickness < 3) |
- style = SOLID; |
- |
- switch (style) { |
- case BNONE: |
- case BHIDDEN: |
- return; |
- case DOTTED: |
- case DASHED: |
- drawDashedOrDottedBoxSide(graphicsContext, x1, y1, x2, y2, side, |
- color, thickness, style, antialias); |
- break; |
- case DOUBLE: |
- drawDoubleBoxSide(graphicsContext, x1, y1, x2, y2, length, side, color, |
- thickness, adjacentWidth1, adjacentWidth2, antialias); |
- break; |
- case RIDGE: |
- case GROOVE: |
- drawRidgeOrGrooveBoxSide(graphicsContext, x1, y1, x2, y2, side, color, |
- style, adjacentWidth1, adjacentWidth2, antialias); |
- break; |
- case INSET: |
- // FIXME: Maybe we should lighten the colors on one side like Firefox. |
- // https://bugs.webkit.org/show_bug.cgi?id=58608 |
- if (side == BSTop || side == BSLeft) |
- color = color.dark(); |
- // fall through |
- case OUTSET: |
- if (style == OUTSET && (side == BSBottom || side == BSRight)) |
- color = color.dark(); |
- // fall through |
- case SOLID: |
- drawSolidBoxSide(graphicsContext, x1, y1, x2, y2, side, color, adjacentWidth1, adjacentWidth2, antialias); |
- break; |
- } |
-} |
- |
-void RenderObject::drawDashedOrDottedBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, |
- BoxSide side, Color color, int thickness, EBorderStyle style, bool antialias) |
-{ |
- if (thickness <= 0) |
- return; |
- |
- bool wasAntialiased = graphicsContext->shouldAntialias(); |
- StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle(); |
- graphicsContext->setShouldAntialias(antialias); |
- graphicsContext->setStrokeColor(color); |
- graphicsContext->setStrokeThickness(thickness); |
- graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke); |
- |
- switch (side) { |
- case BSBottom: |
- case BSTop: |
- graphicsContext->drawLine(IntPoint(x1, (y1 + y2) / 2), IntPoint(x2, (y1 + y2) / 2)); |
- break; |
- case BSRight: |
- case BSLeft: |
- graphicsContext->drawLine(IntPoint((x1 + x2) / 2, y1), IntPoint((x1 + x2) / 2, y2)); |
- break; |
- } |
- graphicsContext->setShouldAntialias(wasAntialiased); |
- graphicsContext->setStrokeStyle(oldStrokeStyle); |
-} |
- |
-void RenderObject::drawDoubleBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, |
- int length, BoxSide side, Color color, int thickness, int adjacentWidth1, int adjacentWidth2, bool antialias) |
-{ |
- int thirdOfThickness = (thickness + 1) / 3; |
- ASSERT(thirdOfThickness); |
- |
- if (!adjacentWidth1 && !adjacentWidth2) { |
- StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle(); |
- graphicsContext->setStrokeStyle(NoStroke); |
- graphicsContext->setFillColor(color); |
- |
- bool wasAntialiased = graphicsContext->shouldAntialias(); |
- graphicsContext->setShouldAntialias(antialias); |
- |
- switch (side) { |
- case BSTop: |
- case BSBottom: |
- graphicsContext->drawRect(IntRect(x1, y1, length, thirdOfThickness)); |
- graphicsContext->drawRect(IntRect(x1, y2 - thirdOfThickness, length, thirdOfThickness)); |
- break; |
- case BSLeft: |
- case BSRight: |
- // FIXME: Why do we offset the border by 1 in this case but not the other one? |
- if (length > 1) { |
- graphicsContext->drawRect(IntRect(x1, y1 + 1, thirdOfThickness, length - 1)); |
- graphicsContext->drawRect(IntRect(x2 - thirdOfThickness, y1 + 1, thirdOfThickness, length - 1)); |
- } |
- break; |
- } |
- |
- graphicsContext->setShouldAntialias(wasAntialiased); |
- graphicsContext->setStrokeStyle(oldStrokeStyle); |
- return; |
- } |
- |
- int adjacent1BigThird = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 3; |
- int adjacent2BigThird = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 3; |
- |
- switch (side) { |
- case BSTop: |
- drawLineForBoxSide(graphicsContext, x1 + std::max((-adjacentWidth1 * 2 + 1) / 3, 0), |
- y1, x2 - std::max((-adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness, |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- drawLineForBoxSide(graphicsContext, x1 + std::max((adjacentWidth1 * 2 + 1) / 3, 0), |
- y2 - thirdOfThickness, x2 - std::max((adjacentWidth2 * 2 + 1) / 3, 0), y2, |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- break; |
- case BSLeft: |
- drawLineForBoxSide(graphicsContext, x1, y1 + std::max((-adjacentWidth1 * 2 + 1) / 3, 0), |
- x1 + thirdOfThickness, y2 - std::max((-adjacentWidth2 * 2 + 1) / 3, 0), |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + std::max((adjacentWidth1 * 2 + 1) / 3, 0), |
- x2, y2 - std::max((adjacentWidth2 * 2 + 1) / 3, 0), |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- break; |
- case BSBottom: |
- drawLineForBoxSide(graphicsContext, x1 + std::max((adjacentWidth1 * 2 + 1) / 3, 0), |
- y1, x2 - std::max((adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness, |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- drawLineForBoxSide(graphicsContext, x1 + std::max((-adjacentWidth1 * 2 + 1) / 3, 0), |
- y2 - thirdOfThickness, x2 - std::max((-adjacentWidth2 * 2 + 1) / 3, 0), y2, |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- break; |
- case BSRight: |
- drawLineForBoxSide(graphicsContext, x1, y1 + std::max((adjacentWidth1 * 2 + 1) / 3, 0), |
- x1 + thirdOfThickness, y2 - std::max((adjacentWidth2 * 2 + 1) / 3, 0), |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + std::max((-adjacentWidth1 * 2 + 1) / 3, 0), |
- x2, y2 - std::max((-adjacentWidth2 * 2 + 1) / 3, 0), |
- side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias); |
- break; |
- default: |
- break; |
- } |
-} |
- |
-void RenderObject::drawRidgeOrGrooveBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, |
- BoxSide side, Color color, EBorderStyle style, int adjacentWidth1, int adjacentWidth2, bool antialias) |
-{ |
- EBorderStyle s1; |
- EBorderStyle s2; |
- if (style == GROOVE) { |
- s1 = INSET; |
- s2 = OUTSET; |
- } else { |
- s1 = OUTSET; |
- s2 = INSET; |
- } |
- |
- int adjacent1BigHalf = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 2; |
- int adjacent2BigHalf = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 2; |
- |
- switch (side) { |
- case BSTop: |
- drawLineForBoxSide(graphicsContext, x1 + std::max(-adjacentWidth1, 0) / 2, y1, x2 - std::max(-adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2, |
- side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias); |
- drawLineForBoxSide(graphicsContext, x1 + std::max(adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - std::max(adjacentWidth2 + 1, 0) / 2, y2, |
- side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias); |
- break; |
- case BSLeft: |
- drawLineForBoxSide(graphicsContext, x1, y1 + std::max(-adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - std::max(-adjacentWidth2, 0) / 2, |
- side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias); |
- drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + std::max(adjacentWidth1 + 1, 0) / 2, x2, y2 - std::max(adjacentWidth2 + 1, 0) / 2, |
- side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias); |
- break; |
- case BSBottom: |
- drawLineForBoxSide(graphicsContext, x1 + std::max(adjacentWidth1, 0) / 2, y1, x2 - std::max(adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2, |
- side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias); |
- drawLineForBoxSide(graphicsContext, x1 + std::max(-adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - std::max(-adjacentWidth2 + 1, 0) / 2, y2, |
- side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias); |
- break; |
- case BSRight: |
- drawLineForBoxSide(graphicsContext, x1, y1 + std::max(adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - std::max(adjacentWidth2, 0) / 2, |
- side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias); |
- drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + std::max(-adjacentWidth1 + 1, 0) / 2, x2, y2 - std::max(-adjacentWidth2 + 1, 0) / 2, |
- side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias); |
- break; |
- } |
-} |
- |
-void RenderObject::drawSolidBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2, |
- BoxSide side, Color color, int adjacentWidth1, int adjacentWidth2, bool antialias) |
-{ |
- StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle(); |
- graphicsContext->setStrokeStyle(NoStroke); |
- graphicsContext->setFillColor(color); |
- ASSERT(x2 >= x1); |
- ASSERT(y2 >= y1); |
- if (!adjacentWidth1 && !adjacentWidth2) { |
- // Turn off antialiasing to match the behavior of drawConvexPolygon(); |
- // this matters for rects in transformed contexts. |
- bool wasAntialiased = graphicsContext->shouldAntialias(); |
- graphicsContext->setShouldAntialias(antialias); |
- graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1)); |
- graphicsContext->setShouldAntialias(wasAntialiased); |
- graphicsContext->setStrokeStyle(oldStrokeStyle); |
- return; |
- } |
- FloatPoint quad[4]; |
- switch (side) { |
- case BSTop: |
- quad[0] = FloatPoint(x1 + std::max(-adjacentWidth1, 0), y1); |
- quad[1] = FloatPoint(x1 + std::max(adjacentWidth1, 0), y2); |
- quad[2] = FloatPoint(x2 - std::max(adjacentWidth2, 0), y2); |
- quad[3] = FloatPoint(x2 - std::max(-adjacentWidth2, 0), y1); |
- break; |
- case BSBottom: |
- quad[0] = FloatPoint(x1 + std::max(adjacentWidth1, 0), y1); |
- quad[1] = FloatPoint(x1 + std::max(-adjacentWidth1, 0), y2); |
- quad[2] = FloatPoint(x2 - std::max(-adjacentWidth2, 0), y2); |
- quad[3] = FloatPoint(x2 - std::max(adjacentWidth2, 0), y1); |
- break; |
- case BSLeft: |
- quad[0] = FloatPoint(x1, y1 + std::max(-adjacentWidth1, 0)); |
- quad[1] = FloatPoint(x1, y2 - std::max(-adjacentWidth2, 0)); |
- quad[2] = FloatPoint(x2, y2 - std::max(adjacentWidth2, 0)); |
- quad[3] = FloatPoint(x2, y1 + std::max(adjacentWidth1, 0)); |
- break; |
- case BSRight: |
- quad[0] = FloatPoint(x1, y1 + std::max(adjacentWidth1, 0)); |
- quad[1] = FloatPoint(x1, y2 - std::max(adjacentWidth2, 0)); |
- quad[2] = FloatPoint(x2, y2 - std::max(-adjacentWidth2, 0)); |
- quad[3] = FloatPoint(x2, y1 + std::max(-adjacentWidth1, 0)); |
- break; |
- } |
- |
- graphicsContext->drawConvexPolygon(4, quad, antialias); |
- graphicsContext->setStrokeStyle(oldStrokeStyle); |
-} |
- |
-void RenderObject::paintFocusRing(PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderStyle* style) |
-{ |
- Vector<LayoutRect> focusRingRects; |
- addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer()); |
- ASSERT(style->outlineStyleIsAuto()); |
- Vector<IntRect> focusRingIntRects; |
- for (size_t i = 0; i < focusRingRects.size(); ++i) |
- focusRingIntRects.append(pixelSnappedIntRect(focusRingRects[i])); |
- paintInfo.context->drawFocusRing(focusRingIntRects, style->outlineWidth(), style->outlineOffset(), resolveColor(style, CSSPropertyOutlineColor)); |
-} |
- |
void RenderObject::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRect) |
{ |
- RenderStyle* styleToUse = style(); |
- if (!styleToUse->hasOutline()) |
- return; |
- |
- LayoutUnit outlineWidth = styleToUse->outlineWidth(); |
- |
- int outlineOffset = styleToUse->outlineOffset(); |
- |
- if (styleToUse->outlineStyleIsAuto()) { |
- if (RenderTheme::theme().shouldDrawDefaultFocusRing(this)) { |
- // Only paint the focus ring by hand if the theme isn't able to draw the focus ring. |
- paintFocusRing(paintInfo, paintRect.location(), styleToUse); |
- } |
- return; |
- } |
- |
- if (styleToUse->outlineStyle() == BNONE) |
- return; |
- |
- IntRect inner = pixelSnappedIntRect(paintRect); |
- inner.inflate(outlineOffset); |
- |
- IntRect outer = pixelSnappedIntRect(inner); |
- outer.inflate(outlineWidth); |
- |
- // FIXME: This prevents outlines from painting inside the object. See bug 12042 |
- if (outer.isEmpty()) |
- return; |
- |
- EBorderStyle outlineStyle = styleToUse->outlineStyle(); |
- Color outlineColor = resolveColor(styleToUse, CSSPropertyOutlineColor); |
- |
- GraphicsContext* graphicsContext = paintInfo.context; |
- bool useTransparencyLayer = outlineColor.hasAlpha(); |
- if (useTransparencyLayer) { |
- if (outlineStyle == SOLID) { |
- Path path; |
- path.addRect(outer); |
- path.addRect(inner); |
- graphicsContext->setFillRule(RULE_EVENODD); |
- graphicsContext->setFillColor(outlineColor); |
- graphicsContext->fillPath(path); |
- return; |
- } |
- graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255); |
- outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue()); |
- } |
- |
- int leftOuter = outer.x(); |
- int leftInner = inner.x(); |
- int rightOuter = outer.maxX(); |
- int rightInner = inner.maxX(); |
- int topOuter = outer.y(); |
- int topInner = inner.y(); |
- int bottomOuter = outer.maxY(); |
- int bottomInner = inner.maxY(); |
- |
- drawLineForBoxSide(graphicsContext, leftOuter, topOuter, leftInner, bottomOuter, BSLeft, outlineColor, outlineStyle, outlineWidth, outlineWidth); |
- drawLineForBoxSide(graphicsContext, leftOuter, topOuter, rightOuter, topInner, BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth); |
- drawLineForBoxSide(graphicsContext, rightInner, topOuter, rightOuter, bottomOuter, BSRight, outlineColor, outlineStyle, outlineWidth, outlineWidth); |
- drawLineForBoxSide(graphicsContext, leftOuter, bottomInner, rightOuter, bottomOuter, BSBottom, outlineColor, outlineStyle, outlineWidth, outlineWidth); |
- |
- if (useTransparencyLayer) |
- graphicsContext->endLayer(); |
+ ObjectPainter(*this).paintOutline(paintInfo, paintRect); |
} |
void RenderObject::addChildFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer) const |