| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/InlinePainter.h" | 6 #include "core/paint/InlinePainter.h" |
| 7 | 7 |
| 8 #include "core/layout/LayoutBlock.h" | 8 #include "core/layout/LayoutBlock.h" |
| 9 #include "core/layout/LayoutInline.h" | 9 #include "core/layout/LayoutInline.h" |
| 10 #include "core/layout/LayoutTheme.h" | 10 #include "core/layout/LayoutTheme.h" |
| 11 #include "core/layout/line/RootInlineBox.h" | 11 #include "core/layout/line/RootInlineBox.h" |
| 12 #include "core/paint/BoxPainter.h" | 12 #include "core/paint/BoxPainter.h" |
| 13 #include "core/paint/LayoutObjectDrawingRecorder.h" | 13 #include "core/paint/LayoutObjectDrawingRecorder.h" |
| 14 #include "core/paint/LineBoxListPainter.h" | 14 #include "core/paint/LineBoxListPainter.h" |
| 15 #include "core/paint/ObjectPainter.h" | 15 #include "core/paint/ObjectPainter.h" |
| 16 #include "core/paint/PaintInfo.h" | 16 #include "core/paint/PaintInfo.h" |
| 17 #include "platform/geometry/LayoutPoint.h" | 17 #include "platform/geometry/LayoutPoint.h" |
| 18 #include <limits> | 18 #include <limits> |
| 19 | 19 |
| 20 namespace blink { | 20 namespace blink { |
| 21 | 21 |
| 22 void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) | 22 void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) |
| 23 { | 23 { |
| 24 // FIXME: When Skia supports annotation rect covering (https://code.google.c
om/p/skia/issues/detail?id=3872), | 24 // FIXME: When Skia supports annotation rect covering (https://code.google.c
om/p/skia/issues/detail?id=3872), |
| 25 // this rect may be covered by foreground and descendant drawings. Then we m
ay need a dedicated paint phase. | 25 // this rect may be covered by foreground and descendant drawings. Then we m
ay need a dedicated paint phase. |
| 26 if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting()) | 26 if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting()) |
| 27 ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffs
et); | 27 ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffs
et); |
| 28 | 28 |
| 29 if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSel
fOutline || paintInfo.phase == PaintPhaseChildOutlines) { |
| 30 ObjectPainter painter(m_layoutInline); |
| 31 if (paintInfo.phase != PaintPhaseSelfOutline) |
| 32 painter.paintInlineChildrenOutlines(paintInfo, paintOffset); |
| 33 if (paintInfo.phase != PaintPhaseChildOutlines && !m_layoutInline.isElem
entContinuation()) |
| 34 painter.paintOutline(paintInfo, paintOffset); |
| 35 return; |
| 36 } |
| 37 |
| 29 LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paint
Info, paintOffset); | 38 LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paint
Info, paintOffset); |
| 30 } | 39 } |
| 31 | 40 |
| 32 LayoutRect InlinePainter::outlinePaintRect(const Vector<LayoutRect>& outlineRect
s, const LayoutPoint& paintOffset) const | |
| 33 { | |
| 34 int outlineOutset = m_layoutInline.styleRef().outlineOutsetExtent(); | |
| 35 LayoutRect outlineRect; | |
| 36 for (const LayoutRect& rect : outlineRects) { | |
| 37 LayoutRect inflatedRect(rect); | |
| 38 // Inflate the individual rects instead of the union, to avoid losing | |
| 39 // rects which have degenerate width/height (== isEmpty() true.) | |
| 40 inflatedRect.inflate(outlineOutset); | |
| 41 outlineRect.unite(inflatedRect); | |
| 42 } | |
| 43 outlineRect.moveBy(paintOffset); | |
| 44 return outlineRect; | |
| 45 } | |
| 46 | |
| 47 void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) | |
| 48 { | |
| 49 const ComputedStyle& styleToUse = m_layoutInline.styleRef(); | |
| 50 if (!styleToUse.hasOutline()) | |
| 51 return; | |
| 52 | |
| 53 if (styleToUse.outlineStyleIsAuto()) { | |
| 54 if (!LayoutTheme::theme().shouldDrawDefaultFocusRing(&m_layoutInline)) | |
| 55 return; | |
| 56 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.c
ontext, m_layoutInline, paintInfo.phase)) | |
| 57 return; | |
| 58 | |
| 59 Vector<LayoutRect> focusRingRects; | |
| 60 m_layoutInline.addOutlineRects(focusRingRects, paintOffset); | |
| 61 | |
| 62 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutInline,
paintInfo.phase, outlinePaintRect(focusRingRects, LayoutPoint())); | |
| 63 // Only paint the focus ring by hand if the theme isn't able to draw the
focus ring. | |
| 64 ObjectPainter(m_layoutInline).paintFocusRing(paintInfo, styleToUse, focu
sRingRects); | |
| 65 return; | |
| 66 } | |
| 67 | |
| 68 if (styleToUse.outlineStyle() == BNONE) | |
| 69 return; | |
| 70 | |
| 71 GraphicsContext* graphicsContext = paintInfo.context; | |
| 72 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*graphicsContext
, m_layoutInline, paintInfo.phase)) | |
| 73 return; | |
| 74 | |
| 75 Vector<LayoutRect> rects; | |
| 76 | |
| 77 rects.append(LayoutRect()); | |
| 78 for (InlineFlowBox* curr = m_layoutInline.firstLineBox(); curr; curr = curr-
>nextLineBox()) { | |
| 79 RootInlineBox& root = curr->root(); | |
| 80 LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop()
); | |
| 81 LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logica
lBottom()); | |
| 82 rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - t
op)); | |
| 83 } | |
| 84 rects.append(LayoutRect()); | |
| 85 | |
| 86 Color outlineColor = m_layoutInline.resolveColor(styleToUse, CSSPropertyOutl
ineColor); | |
| 87 bool useTransparencyLayer = outlineColor.hasAlpha(); | |
| 88 | |
| 89 LayoutObjectDrawingRecorder recorder(*graphicsContext, m_layoutInline, paint
Info.phase, outlinePaintRect(rects, paintOffset)); | |
| 90 if (useTransparencyLayer) { | |
| 91 graphicsContext->beginLayer(static_cast<float>(outlineColor.alpha()) / 2
55); | |
| 92 outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineCo
lor.blue()); | |
| 93 } | |
| 94 | |
| 95 for (unsigned i = 1; i < rects.size() - 1; i++) | |
| 96 paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects
.at(i), rects.at(i + 1), outlineColor); | |
| 97 | |
| 98 if (useTransparencyLayer) | |
| 99 graphicsContext->endLayer(); | |
| 100 } | |
| 101 | |
| 102 static IntRect pixelSnappedOutsetPaintRect(const LayoutRect& baseRect, const Lay
outPoint& paintOffset, int outset) | |
| 103 { | |
| 104 LayoutRect box(baseRect); | |
| 105 box.moveBy(paintOffset); | |
| 106 box.inflate(outset); | |
| 107 return pixelSnappedIntRect(box); | |
| 108 } | |
| 109 | |
| 110 void InlinePainter::paintOutlineForLine(GraphicsContext* graphicsContext, const
LayoutPoint& paintOffset, | |
| 111 const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& ne
xtline, const Color outlineColor) | |
| 112 { | |
| 113 const ComputedStyle& styleToUse = m_layoutInline.styleRef(); | |
| 114 int outlineWidth = styleToUse.outlineWidth(); | |
| 115 EBorderStyle outlineStyle = styleToUse.outlineStyle(); | |
| 116 | |
| 117 int offset = m_layoutInline.style()->outlineOffset(); | |
| 118 | |
| 119 IntRect pixelSnappedBox = pixelSnappedOutsetPaintRect(thisline, paintOffset,
offset); | |
| 120 if (pixelSnappedBox.width() < 0 || pixelSnappedBox.height() < 0) | |
| 121 return; | |
| 122 // Note that we use IntRect below for working with solely x/width values, si
mplifying logic at cost of a bit of memory. | |
| 123 IntRect pixelSnappedLastLine = pixelSnappedOutsetPaintRect(lastline, paintOf
fset, offset); | |
| 124 IntRect pixelSnappedNextLine = pixelSnappedOutsetPaintRect(nextline, paintOf
fset, offset); | |
| 125 | |
| 126 const int fallbackMaxOutlineX = std::numeric_limits<int>::max(); | |
| 127 const int fallbackMinOutlineX = std::numeric_limits<int>::min(); | |
| 128 | |
| 129 // left edge | |
| 130 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 131 pixelSnappedBox.x() - outlineWidth, | |
| 132 pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x()
|| (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), | |
| 133 pixelSnappedBox.x(), | |
| 134 pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline
.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0), | |
| 135 BSLeft, | |
| 136 outlineColor, outlineStyle, | |
| 137 (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() -
1) <= thisline.x() ? outlineWidth : -outlineWidth), | |
| 138 (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX()
- 1) <= thisline.x() ? outlineWidth : -outlineWidth), | |
| 139 false); | |
| 140 | |
| 141 // right edge | |
| 142 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 143 pixelSnappedBox.maxX(), | |
| 144 pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.
maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0), | |
| 145 pixelSnappedBox.maxX() + outlineWidth, | |
| 146 pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisl
ine.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0), | |
| 147 BSRight, | |
| 148 outlineColor, outlineStyle, | |
| 149 (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.ma
xX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth), | |
| 150 (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.m
axX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth), | |
| 151 false); | |
| 152 // upper edge | |
| 153 if (thisline.x() < lastline.x()) { | |
| 154 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 155 pixelSnappedBox.x() - outlineWidth, | |
| 156 pixelSnappedBox.y() - outlineWidth, | |
| 157 std::min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty()
? fallbackMaxOutlineX : pixelSnappedLastLine.x())), | |
| 158 pixelSnappedBox.y(), | |
| 159 BSTop, outlineColor, outlineStyle, | |
| 160 outlineWidth, | |
| 161 (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSn
appedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, | |
| 162 false); | |
| 163 } | |
| 164 | |
| 165 if (lastline.maxX() < thisline.maxX()) { | |
| 166 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 167 std::max(lastline.isEmpty() ? fallbackMinOutlineX : pixelSnappedLast
Line.maxX(), pixelSnappedBox.x() - outlineWidth), | |
| 168 pixelSnappedBox.y() - outlineWidth, | |
| 169 pixelSnappedBox.maxX() + outlineWidth, | |
| 170 pixelSnappedBox.y(), | |
| 171 BSTop, outlineColor, outlineStyle, | |
| 172 (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOf
fset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth, | |
| 173 outlineWidth, false); | |
| 174 } | |
| 175 | |
| 176 if (thisline.x() == thisline.maxX()) { | |
| 177 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 178 pixelSnappedBox.x() - outlineWidth, | |
| 179 pixelSnappedBox.y() - outlineWidth, | |
| 180 pixelSnappedBox.maxX() + outlineWidth, | |
| 181 pixelSnappedBox.y(), | |
| 182 BSTop, outlineColor, outlineStyle, | |
| 183 outlineWidth, | |
| 184 outlineWidth, | |
| 185 false); | |
| 186 } | |
| 187 | |
| 188 // lower edge | |
| 189 if (thisline.x() < nextline.x()) { | |
| 190 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 191 pixelSnappedBox.x() - outlineWidth, | |
| 192 pixelSnappedBox.maxY(), | |
| 193 std::min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty()
? pixelSnappedNextLine.x() + 1 : fallbackMaxOutlineX), | |
| 194 pixelSnappedBox.maxY() + outlineWidth, | |
| 195 BSBottom, outlineColor, outlineStyle, | |
| 196 outlineWidth, | |
| 197 (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSn
appedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth, | |
| 198 false); | |
| 199 } | |
| 200 | |
| 201 if (nextline.maxX() < thisline.maxX()) { | |
| 202 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 203 std::max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : fallbac
kMinOutlineX, pixelSnappedBox.x() - outlineWidth), | |
| 204 pixelSnappedBox.maxY(), | |
| 205 pixelSnappedBox.maxX() + outlineWidth, | |
| 206 pixelSnappedBox.maxY() + outlineWidth, | |
| 207 BSBottom, outlineColor, outlineStyle, | |
| 208 (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOf
fset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth, | |
| 209 outlineWidth, false); | |
| 210 } | |
| 211 | |
| 212 if (thisline.x() == thisline.maxX()) { | |
| 213 ObjectPainter::drawLineForBoxSide(graphicsContext, | |
| 214 pixelSnappedBox.x() - outlineWidth, | |
| 215 pixelSnappedBox.maxY(), | |
| 216 pixelSnappedBox.maxX() + outlineWidth, | |
| 217 pixelSnappedBox.maxY() + outlineWidth, | |
| 218 BSBottom, outlineColor, outlineStyle, | |
| 219 outlineWidth, | |
| 220 outlineWidth, | |
| 221 false); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 } // namespace blink | 41 } // namespace blink |
| OLD | NEW |