Commit 378e044a authored by wkorman's avatar wkorman Committed by Commit bot

Include any text shadow bounds in SVG text cull rect.

BUG=628414

Review-Url: https://codereview.chromium.org/2162033003
Cr-Commit-Position: refs/heads/master@{#406612}
parent 058b59c9
...@@ -38,8 +38,14 @@ bool SVGInlineTextBoxPainter::shouldPaintSelection(const PaintInfo& paintInfo) c ...@@ -38,8 +38,14 @@ bool SVGInlineTextBoxPainter::shouldPaintSelection(const PaintInfo& paintInfo) c
return !paintInfo.isPrinting() && m_svgInlineTextBox.getSelectionState() != SelectionNone; return !paintInfo.isPrinting() && m_svgInlineTextBox.getSelectionState() != SelectionNone;
} }
static bool hasShadow(const PaintInfo& paintInfo, const ComputedStyle& style)
{
// Text shadows are disabled when printing. http://crbug.com/258321
return style.textShadow() && !paintInfo.isPrinting();
}
FloatRect SVGInlineTextBoxPainter::boundsForDrawingRecorder( FloatRect SVGInlineTextBoxPainter::boundsForDrawingRecorder(
const LayoutPoint& paintOffset, bool includeSelectionRect) const const PaintInfo& paintInfo, const ComputedStyle& style, const LayoutPoint& paintOffset, bool includeSelectionRect) const
{ {
// We compute the paint rect with what looks like the logical values, to match the // We compute the paint rect with what looks like the logical values, to match the
// computation in SVGInlineTextBox::calculateBoundaries, and the fact that vertical (etc) // computation in SVGInlineTextBox::calculateBoundaries, and the fact that vertical (etc)
...@@ -47,6 +53,8 @@ FloatRect SVGInlineTextBoxPainter::boundsForDrawingRecorder( ...@@ -47,6 +53,8 @@ FloatRect SVGInlineTextBoxPainter::boundsForDrawingRecorder(
LayoutRect bounds( LayoutRect bounds(
LayoutPoint(m_svgInlineTextBox.topLeft() + paintOffset), LayoutPoint(m_svgInlineTextBox.topLeft() + paintOffset),
LayoutSize(m_svgInlineTextBox.logicalWidth(), m_svgInlineTextBox.logicalHeight())); LayoutSize(m_svgInlineTextBox.logicalWidth(), m_svgInlineTextBox.logicalHeight()));
if (hasShadow(paintInfo, style))
bounds.expand(style.textShadow()->rectOutsetsIncludingOriginal());
if (includeSelectionRect) { if (includeSelectionRect) {
bounds.unite(m_svgInlineTextBox.localSelectionRect( bounds.unite(m_svgInlineTextBox.localSelectionRect(
m_svgInlineTextBox.start(), m_svgInlineTextBox.start() + m_svgInlineTextBox.len())); m_svgInlineTextBox.start(), m_svgInlineTextBox.start() + m_svgInlineTextBox.len()));
...@@ -81,7 +89,7 @@ void SVGInlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoin ...@@ -81,7 +89,7 @@ void SVGInlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoin
bool includeSelectionRect = paintInfo.phase != PaintPhaseSelection bool includeSelectionRect = paintInfo.phase != PaintPhaseSelection
&& (haveSelection || InlineTextBoxPainter::paintsMarkerHighlights(textLayoutObject)); && (haveSelection || InlineTextBoxPainter::paintsMarkerHighlights(textLayoutObject));
DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayItemType, DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayItemType,
boundsForDrawingRecorder(paintOffset, includeSelectionRect)); boundsForDrawingRecorder(paintInfo, style, paintOffset, includeSelectionRect));
InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers(
paintInfo, paintOffset, style, paintInfo, paintOffset, style,
textLayoutObject.scaledFont(), DocumentMarkerPaintPhase::Background); textLayoutObject.scaledFont(), DocumentMarkerPaintPhase::Background);
...@@ -314,11 +322,6 @@ bool SVGInlineTextBoxPainter::setupTextPaint(const PaintInfo& paintInfo, const C ...@@ -314,11 +322,6 @@ bool SVGInlineTextBoxPainter::setupTextPaint(const PaintInfo& paintInfo, const C
float scalingFactor = textLayoutObject.scalingFactor(); float scalingFactor = textLayoutObject.scalingFactor();
ASSERT(scalingFactor); ASSERT(scalingFactor);
const ShadowList* shadowList = style.textShadow();
// Text shadows are disabled when printing. http://crbug.com/258321
bool hasShadow = shadowList && !paintInfo.isPrinting();
AffineTransform paintServerTransform; AffineTransform paintServerTransform;
const AffineTransform* additionalPaintServerTransform = 0; const AffineTransform* additionalPaintServerTransform = 0;
...@@ -332,8 +335,8 @@ bool SVGInlineTextBoxPainter::setupTextPaint(const PaintInfo& paintInfo, const C ...@@ -332,8 +335,8 @@ bool SVGInlineTextBoxPainter::setupTextPaint(const PaintInfo& paintInfo, const C
return false; return false;
paint.setAntiAlias(true); paint.setAntiAlias(true);
if (hasShadow) { if (hasShadow(paintInfo, style)) {
std::unique_ptr<DrawLooperBuilder> drawLooperBuilder = shadowList->createDrawLooper(DrawLooperBuilder::ShadowRespectsAlpha, style.visitedDependentColor(CSSPropertyColor)); std::unique_ptr<DrawLooperBuilder> drawLooperBuilder = style.textShadow()->createDrawLooper(DrawLooperBuilder::ShadowRespectsAlpha, style.visitedDependentColor(CSSPropertyColor));
paint.setLooper(toSkSp(drawLooperBuilder->detachDrawLooper())); paint.setLooper(toSkSp(drawLooperBuilder->detachDrawLooper()));
} }
......
...@@ -45,7 +45,7 @@ public: ...@@ -45,7 +45,7 @@ public:
private: private:
bool shouldPaintSelection(const PaintInfo&) const; bool shouldPaintSelection(const PaintInfo&) const;
FloatRect boundsForDrawingRecorder(const LayoutPoint&, bool includeSelectionRect) const; FloatRect boundsForDrawingRecorder(const PaintInfo&, const ComputedStyle&, const LayoutPoint&, bool includeSelectionRect) const;
void paintTextFragments(const PaintInfo&, LayoutObject&); void paintTextFragments(const PaintInfo&, LayoutObject&);
void paintDecoration(const PaintInfo&, TextDecoration, const SVGTextFragment&); void paintDecoration(const PaintInfo&, TextDecoration, const SVGTextFragment&);
bool setupTextPaint(const PaintInfo&, const ComputedStyle&, LayoutSVGResourceMode, SkPaint&); bool setupTextPaint(const PaintInfo&, const ComputedStyle&, LayoutSVGResourceMode, SkPaint&);
......
...@@ -71,24 +71,25 @@ static void assertTextDrawingEquals(const DrawingDisplayItem* drawingDisplayItem ...@@ -71,24 +71,25 @@ static void assertTextDrawingEquals(const DrawingDisplayItem* drawingDisplayItem
ASSERT_EQ(str, static_cast<const InlineTextBox*>(&drawingDisplayItem->client())->text()); ASSERT_EQ(str, static_cast<const InlineTextBox*>(&drawingDisplayItem->client())->text());
} }
const static int kAllowedPixelDelta = 8; bool ApproximatelyEqual(int a, int b, int delta)
{
return abs(a - b) <= delta;
}
const static int kPixelDelta = 4;
#define EXPECT_RECT_EQ(expected, actual) \
do { \
const FloatRect& actualRect = actual; \
EXPECT_TRUE(ApproximatelyEqual(expected.x(), actualRect.x(), kPixelDelta)) << "actual: " << actualRect.x() << ", expected: " << expected.x(); \
EXPECT_TRUE(ApproximatelyEqual(expected.y(), actualRect.y(), kPixelDelta)) << "actual: " << actualRect.y() << ", expected: " << expected.y(); \
EXPECT_TRUE(ApproximatelyEqual(expected.width(), actualRect.width(), kPixelDelta)) << "actual: " << actualRect.width() << ", expected: " << expected.width(); \
EXPECT_TRUE(ApproximatelyEqual(expected.height(), actualRect.height(), kPixelDelta)) << "actual: " << actualRect.height() << ", expected: " << expected.height(); \
} while (false)
static void assertCullRectEquals(const DrawingDisplayItem* drawingDisplayItem, const IntRect& expectedRect) static IntRect cullRectFromDrawing(const DrawingDisplayItem& drawingDisplayItem)
{ {
// Text metrics can vary slightly across platforms, so we allow for a small pixel difference. return IntRect(drawingDisplayItem.picture()->cullRect());
IntRect outerRect(expectedRect);
int delta = kAllowedPixelDelta / 2;
outerRect.expand(IntRectOutsets(delta, delta, delta, delta));
IntRect innerRect(expectedRect);
// Rect contains is inclusive of edge, so shrink by one extra pixel.
int contractDelta = -delta - 1;
innerRect.expand(IntRectOutsets(contractDelta, contractDelta, contractDelta, contractDelta));
IntRect actualRect(IntRect(drawingDisplayItem->picture()->cullRect()));
ASSERT_TRUE(outerRect.contains(actualRect) && !innerRect.contains(actualRect))
<< "Cull rect not approximately equal [expected=("
<< expectedRect.x() << "," << expectedRect.y() << " " << expectedRect.width() << "x" << expectedRect.height() << "), actual=("
<< actualRect.x() << "," << actualRect.y() << " " << actualRect.width() << "x" << actualRect.height() << ")].";
} }
TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_DefaultWritingMode) TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_DefaultWritingMode)
...@@ -101,14 +102,14 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_DefaultWritingMode) ...@@ -101,14 +102,14 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_DefaultWritingMode)
const DrawingDisplayItem* drawingDisplayItem = getDrawingForSVGTextById("target"); const DrawingDisplayItem* drawingDisplayItem = getDrawingForSVGTextById("target");
assertTextDrawingEquals(drawingDisplayItem, "x"); assertTextDrawingEquals(drawingDisplayItem, "x");
assertCullRectEquals(drawingDisplayItem, IntRect(50, 3, 15, 33)); EXPECT_RECT_EQ(IntRect(50, 3, 15, 33), cullRectFromDrawing(*drawingDisplayItem));
selectAllText(); selectAllText();
document().view()->updateAllLifecyclePhases(); document().view()->updateAllLifecyclePhases();
drawingDisplayItem = getDrawingForSVGTextById("target"); drawingDisplayItem = getDrawingForSVGTextById("target");
assertTextDrawingEquals(drawingDisplayItem, "x"); assertTextDrawingEquals(drawingDisplayItem, "x");
assertCullRectEquals(drawingDisplayItem, IntRect(50, 3, 15, 33)); EXPECT_RECT_EQ(IntRect(50, 3, 15, 33), cullRectFromDrawing(*drawingDisplayItem));
} }
TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom) TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom)
...@@ -121,7 +122,7 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom) ...@@ -121,7 +122,7 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom)
const DrawingDisplayItem* drawingDisplayItem = getDrawingForSVGTextById("target"); const DrawingDisplayItem* drawingDisplayItem = getDrawingForSVGTextById("target");
assertTextDrawingEquals(drawingDisplayItem, "x"); assertTextDrawingEquals(drawingDisplayItem, "x");
assertCullRectEquals(drawingDisplayItem, IntRect(33, 30, 34, 15)); EXPECT_RECT_EQ(IntRect(33, 30, 34, 15), cullRectFromDrawing(*drawingDisplayItem));
selectAllText(); selectAllText();
document().view()->updateAllLifecyclePhases(); document().view()->updateAllLifecyclePhases();
...@@ -131,7 +132,20 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom) ...@@ -131,7 +132,20 @@ TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_WritingModeTopToBottom)
// enclosingIntRect() in SVGInlineTextBox::localSelectionRect(). // enclosingIntRect() in SVGInlineTextBox::localSelectionRect().
drawingDisplayItem = getDrawingForSVGTextById("target"); drawingDisplayItem = getDrawingForSVGTextById("target");
assertTextDrawingEquals(drawingDisplayItem, "x"); assertTextDrawingEquals(drawingDisplayItem, "x");
assertCullRectEquals(drawingDisplayItem, IntRect(33, 30, 34, 16)); EXPECT_RECT_EQ(IntRect(33, 30, 34, 16), cullRectFromDrawing(*drawingDisplayItem));
}
TEST_F(SVGInlineTextBoxPainterTest, TextCullRect_TextShadow)
{
setBodyInnerHTML(
"<svg width='400px' height='400px' font-family='Arial' font-size='30'>"
"<text id='target' x='50' y='30' style='text-shadow: 200px 200px 5px red'>x</text>"
"</svg>");
document().view()->updateAllLifecyclePhases();
const DrawingDisplayItem* drawingDisplayItem = getDrawingForSVGTextById("target");
assertTextDrawingEquals(drawingDisplayItem, "x");
EXPECT_RECT_EQ(IntRect(50, 3, 220, 238), cullRectFromDrawing(*drawingDisplayItem));
} }
} // namespace } // namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment