Index: Source/core/paint/InlinePainter.cpp |
diff --git a/Source/core/paint/InlinePainter.cpp b/Source/core/paint/InlinePainter.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..505205960e7b67e6701fff0696cd7430a91d309c |
--- /dev/null |
+++ b/Source/core/paint/InlinePainter.cpp |
@@ -0,0 +1,185 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "core/paint/InlinePainter.h" |
+ |
+#include "core/paint/BoxPainter.h" |
+#include "core/paint/ObjectPainter.h" |
+#include "core/rendering/GraphicsContextAnnotator.h" |
+#include "core/rendering/PaintInfo.h" |
+#include "core/rendering/RenderInline.h" |
+#include "core/rendering/RenderTheme.h" |
+#include "core/rendering/RootInlineBox.h" |
+#include "platform/geometry/LayoutPoint.h" |
+ |
+namespace blink { |
+ |
+void InlinePainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
+{ |
+ ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderInline); |
+ m_renderInline.lineBoxes()->paint(&m_renderInline, paintInfo, paintOffset); |
+} |
+ |
+void InlinePainter::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
+{ |
+ RenderStyle* styleToUse = m_renderInline.style(); |
+ if (!styleToUse->hasOutline()) |
+ return; |
+ |
+ if (styleToUse->outlineStyleIsAuto()) { |
+ if (RenderTheme::theme().shouldDrawDefaultFocusRing(&m_renderInline)) { |
+ // Only paint the focus ring by hand if the theme isn't able to draw the focus ring. |
+ ObjectPainter(m_renderInline).paintFocusRing(paintInfo, paintOffset, styleToUse); |
+ } |
+ return; |
+ } |
+ |
+ if (styleToUse->outlineStyle() == BNONE) |
+ return; |
+ |
+ Vector<LayoutRect> rects; |
+ |
+ rects.append(LayoutRect()); |
+ for (InlineFlowBox* curr = m_renderInline.firstLineBox(); curr; curr = curr->nextLineBox()) { |
+ RootInlineBox& root = curr->root(); |
+ LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop()); |
+ LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom()); |
+ rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top)); |
+ } |
+ rects.append(LayoutRect()); |
+ |
+ Color outlineColor = m_renderInline.resolveColor(styleToUse, CSSPropertyOutlineColor); |
+ bool useTransparencyLayer = outlineColor.hasAlpha(); |
+ |
+ GraphicsContext* graphicsContext = paintInfo.context; |
+ if (useTransparencyLayer) { |
+ graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255); |
+ outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue()); |
+ } |
+ |
+ for (unsigned i = 1; i < rects.size() - 1; i++) |
+ paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor); |
+ |
+ if (useTransparencyLayer) |
+ graphicsContext->endLayer(); |
+} |
+ |
+void InlinePainter::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, |
+ const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline, const Color outlineColor) |
+{ |
+ RenderStyle* styleToUse = m_renderInline.style(); |
+ int outlineWidth = styleToUse->outlineWidth(); |
+ EBorderStyle outlineStyle = styleToUse->outlineStyle(); |
+ |
+ bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext); |
+ |
+ int offset = m_renderInline.style()->outlineOffset(); |
+ |
+ LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset), |
+ LayoutSize(thisline.width() + offset, thisline.height() + offset)); |
+ |
+ IntRect pixelSnappedBox = pixelSnappedIntRect(box); |
+ if (pixelSnappedBox.width() < 0 || pixelSnappedBox.height() < 0) |
+ return; |
+ IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0); |
+ IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0); |
+ |
+ // left edge |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.x() - outlineWidth, |
+ pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), |
+ pixelSnappedBox.x(), |
+ pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), |
+ BSLeft, |
+ outlineColor, outlineStyle, |
+ (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth), |
+ (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth), |
+ antialias); |
+ |
+ // right edge |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.maxX(), |
+ pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0), |
+ pixelSnappedBox.maxX() + outlineWidth, |
+ pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0), |
+ BSRight, |
+ outlineColor, outlineStyle, |
+ (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth), |
+ (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth), |
+ antialias); |
+ // upper edge |
+ if (thisline.x() < lastline.x()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.x() - outlineWidth, |
+ pixelSnappedBox.y() - outlineWidth, |
+ std::min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())), |
+ pixelSnappedBox.y(), |
+ BSTop, outlineColor, outlineStyle, |
+ outlineWidth, |
+ (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, |
+ antialias); |
+ } |
+ |
+ if (lastline.maxX() < thisline.maxX()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ std::max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth), |
+ pixelSnappedBox.y() - outlineWidth, |
+ pixelSnappedBox.maxX() + outlineWidth, |
+ pixelSnappedBox.y(), |
+ BSTop, outlineColor, outlineStyle, |
+ (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth, |
+ outlineWidth, antialias); |
+ } |
+ |
+ if (thisline.x() == thisline.maxX()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.x() - outlineWidth, |
+ pixelSnappedBox.y() - outlineWidth, |
+ pixelSnappedBox.maxX() + outlineWidth, |
+ pixelSnappedBox.y(), |
+ BSTop, outlineColor, outlineStyle, |
+ outlineWidth, |
+ outlineWidth, |
+ antialias); |
+ } |
+ |
+ // lower edge |
+ if (thisline.x() < nextline.x()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.x() - outlineWidth, |
+ pixelSnappedBox.maxY(), |
+ std::min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000), |
+ pixelSnappedBox.maxY() + outlineWidth, |
+ BSBottom, outlineColor, outlineStyle, |
+ outlineWidth, |
+ (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, |
+ antialias); |
+ } |
+ |
+ if (nextline.maxX() < thisline.maxX()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ std::max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth), |
+ pixelSnappedBox.maxY(), |
+ pixelSnappedBox.maxX() + outlineWidth, |
+ pixelSnappedBox.maxY() + outlineWidth, |
+ BSBottom, outlineColor, outlineStyle, |
+ (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth, |
+ outlineWidth, antialias); |
+ } |
+ |
+ if (thisline.x() == thisline.maxX()) { |
+ ObjectPainter::drawLineForBoxSide(graphicsContext, |
+ pixelSnappedBox.x() - outlineWidth, |
+ pixelSnappedBox.maxY(), |
+ pixelSnappedBox.maxX() + outlineWidth, |
+ pixelSnappedBox.maxY() + outlineWidth, |
+ BSBottom, outlineColor, outlineStyle, |
+ outlineWidth, |
+ outlineWidth, |
+ antialias); |
+ } |
+} |
+ |
+} // namespace blink |