Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: third_party/WebKit/Source/core/paint/BoxPainter.cpp

Issue 2392443009: reflow comments in core/paint (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "core/paint/BoxPainter.h" 5 #include "core/paint/BoxPainter.h"
6 6
7 #include "core/HTMLNames.h" 7 #include "core/HTMLNames.h"
8 #include "core/frame/Settings.h" 8 #include "core/frame/Settings.h"
9 #include "core/html/HTMLFrameOwnerElement.h" 9 #include "core/html/HTMLFrameOwnerElement.h"
10 #include "core/layout/ImageQualityController.h" 10 #include "core/layout/ImageQualityController.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 child = child->nextSibling()) 58 child = child->nextSibling())
59 child->paint(childInfo, adjustedPaintOffset); 59 child->paint(childInfo, adjustedPaintOffset);
60 } 60 }
61 61
62 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, 62 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo,
63 const LayoutPoint& paintOffset) { 63 const LayoutPoint& paintOffset) {
64 LayoutRect paintRect; 64 LayoutRect paintRect;
65 Optional<ScrollRecorder> scrollRecorder; 65 Optional<ScrollRecorder> scrollRecorder;
66 if (isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( 66 if (isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
67 &m_layoutBox, paintInfo)) { 67 &m_layoutBox, paintInfo)) {
68 // For the case where we are painting the background into the scrolling cont ents layer 68 // For the case where we are painting the background into the scrolling
69 // of a composited scroller we need to include the entire overflow rect. 69 // contents layer of a composited scroller we need to include the entire
70 // overflow rect.
70 paintRect = m_layoutBox.layoutOverflowRect(); 71 paintRect = m_layoutBox.layoutOverflowRect();
71 scrollRecorder.emplace(paintInfo.context, m_layoutBox, paintInfo.phase, 72 scrollRecorder.emplace(paintInfo.context, m_layoutBox, paintInfo.phase,
72 m_layoutBox.scrolledContentOffset()); 73 m_layoutBox.scrolledContentOffset());
73 74
74 // The background painting code assumes that the borders are part of the pai ntRect so we 75 // The background painting code assumes that the borders are part of the
75 // expand the paintRect by the border size when painting the background into the 76 // paintRect so we expand the paintRect by the border size when painting the
76 // scrolling contents layer. 77 // background into the scrolling contents layer.
77 paintRect.expandEdges(LayoutUnit(m_layoutBox.borderTop()), 78 paintRect.expandEdges(LayoutUnit(m_layoutBox.borderTop()),
78 LayoutUnit(m_layoutBox.borderRight()), 79 LayoutUnit(m_layoutBox.borderRight()),
79 LayoutUnit(m_layoutBox.borderBottom()), 80 LayoutUnit(m_layoutBox.borderBottom()),
80 LayoutUnit(m_layoutBox.borderLeft())); 81 LayoutUnit(m_layoutBox.borderLeft()));
81 } else { 82 } else {
82 paintRect = m_layoutBox.borderBoxRect(); 83 paintRect = m_layoutBox.borderBoxRect();
83 } 84 }
84 85
85 paintRect.moveBy(paintOffset); 86 paintRect.moveBy(paintOffset);
86 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); 87 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
(...skipping 23 matching lines...) Expand all
110 void BoxPainter::paintBoxDecorationBackgroundWithRect( 111 void BoxPainter::paintBoxDecorationBackgroundWithRect(
111 const PaintInfo& paintInfo, 112 const PaintInfo& paintInfo,
112 const LayoutPoint& paintOffset, 113 const LayoutPoint& paintOffset,
113 const LayoutRect& paintRect) { 114 const LayoutRect& paintRect) {
114 bool paintingOverflowContents = 115 bool paintingOverflowContents =
115 isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( 116 isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
116 &m_layoutBox, paintInfo); 117 &m_layoutBox, paintInfo);
117 const ComputedStyle& style = m_layoutBox.styleRef(); 118 const ComputedStyle& style = m_layoutBox.styleRef();
118 119
119 Optional<DisplayItemCacheSkipper> cacheSkipper; 120 Optional<DisplayItemCacheSkipper> cacheSkipper;
120 // Disable cache in under-invalidation checking mode for MediaSliderPart becau se we always paint using the 121 // Disable cache in under-invalidation checking mode for MediaSliderPart
121 // latest data (buffered ranges, current time and duration) which may be diffe rent from the cached data. 122 // because we always paint using the latest data (buffered ranges, current
123 // time and duration) which may be different from the cached data.
122 if ((RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && 124 if ((RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() &&
123 style.appearance() == MediaSliderPart) 125 style.appearance() == MediaSliderPart)
124 // We may paint a delayed-invalidation object before it's actually invalid ated. Note this would be handled for 126 // We may paint a delayed-invalidation object before it's actually
125 // us by LayoutObjectDrawingRecorder but we have to use DrawingRecorder as we may use the scrolling contents 127 // invalidated. Note this would be handled for us by
126 // layer as DisplayItemClient below. 128 // LayoutObjectDrawingRecorder but we have to use DrawingRecorder as we
129 // may use the scrolling contents layer as DisplayItemClient below.
127 || 130 ||
128 m_layoutBox.fullPaintInvalidationReason() == 131 m_layoutBox.fullPaintInvalidationReason() ==
129 PaintInvalidationDelayedFull) { 132 PaintInvalidationDelayedFull) {
130 cacheSkipper.emplace(paintInfo.context); 133 cacheSkipper.emplace(paintInfo.context);
131 } 134 }
132 135
133 const DisplayItemClient& displayItemClient = 136 const DisplayItemClient& displayItemClient =
134 paintingOverflowContents ? static_cast<const DisplayItemClient&>( 137 paintingOverflowContents ? static_cast<const DisplayItemClient&>(
135 *m_layoutBox.layer() 138 *m_layoutBox.layer()
136 ->compositedLayerMapping() 139 ->compositedLayerMapping()
137 ->scrollingContentsLayer()) 140 ->scrollingContentsLayer())
138 : m_layoutBox; 141 : m_layoutBox;
139 if (DrawingRecorder::useCachedDrawingIfPossible( 142 if (DrawingRecorder::useCachedDrawingIfPossible(
140 paintInfo.context, displayItemClient, 143 paintInfo.context, displayItemClient,
141 DisplayItem::kBoxDecorationBackground)) 144 DisplayItem::kBoxDecorationBackground))
142 return; 145 return;
143 146
144 DrawingRecorder recorder( 147 DrawingRecorder recorder(
145 paintInfo.context, displayItemClient, 148 paintInfo.context, displayItemClient,
146 DisplayItem::kBoxDecorationBackground, 149 DisplayItem::kBoxDecorationBackground,
147 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset))); 150 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset)));
148 BoxDecorationData boxDecorationData(m_layoutBox); 151 BoxDecorationData boxDecorationData(m_layoutBox);
149 GraphicsContextStateSaver stateSaver(paintInfo.context, false); 152 GraphicsContextStateSaver stateSaver(paintInfo.context, false);
150 153
151 if (!paintingOverflowContents) { 154 if (!paintingOverflowContents) {
152 // FIXME: Should eventually give the theme control over whether the box shad ow should paint, since controls could have 155 // FIXME: Should eventually give the theme control over whether the box
153 // custom shadows of their own. 156 // shadow should paint, since controls could have custom shadows of their
157 // own.
154 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground( 158 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(
155 boxDecorationData.bleedAvoidance)) { 159 boxDecorationData.bleedAvoidance)) {
156 paintBoxShadow(paintInfo, paintRect, style, Normal); 160 paintBoxShadow(paintInfo, paintRect, style, Normal);
157 } 161 }
158 162
159 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) { 163 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) {
160 stateSaver.save(); 164 stateSaver.save();
161 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); 165 FloatRoundedRect border = style.getRoundedBorderFor(paintRect);
162 paintInfo.context.clipRoundedRect(border); 166 paintInfo.context.clipRoundedRect(border);
163 167
164 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer) 168 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer)
165 paintInfo.context.beginLayer(); 169 paintInfo.context.beginLayer();
166 } 170 }
167 } 171 }
168 172
169 // If we have a native theme appearance, paint that before painting our backgr ound. 173 // If we have a native theme appearance, paint that before painting our
170 // The theme will tell us whether or not we should also paint the CSS backgrou nd. 174 // background. The theme will tell us whether or not we should also paint the
175 // CSS background.
171 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); 176 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
172 ThemePainter& themePainter = LayoutTheme::theme().painter(); 177 ThemePainter& themePainter = LayoutTheme::theme().painter();
173 bool themePainted = 178 bool themePainted =
174 boxDecorationData.hasAppearance && 179 boxDecorationData.hasAppearance &&
175 !themePainter.paint(m_layoutBox, paintInfo, snappedPaintRect); 180 !themePainter.paint(m_layoutBox, paintInfo, snappedPaintRect);
176 bool shouldPaintBackground = 181 bool shouldPaintBackground =
177 !themePainted && (!paintInfo.skipRootBackground() || 182 !themePainted && (!paintInfo.skipRootBackground() ||
178 paintInfo.paintContainer() != &m_layoutBox); 183 paintInfo.paintContainer() != &m_layoutBox);
179 if (shouldPaintBackground) { 184 if (shouldPaintBackground) {
180 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor, 185 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor,
181 boxDecorationData.bleedAvoidance); 186 boxDecorationData.bleedAvoidance);
182 187
183 if (boxDecorationData.hasAppearance) 188 if (boxDecorationData.hasAppearance)
184 themePainter.paintDecorations(m_layoutBox, paintInfo, snappedPaintRect); 189 themePainter.paintDecorations(m_layoutBox, paintInfo, snappedPaintRect);
185 } 190 }
186 191
187 if (!paintingOverflowContents) { 192 if (!paintingOverflowContents) {
188 paintBoxShadow(paintInfo, paintRect, style, Inset); 193 paintBoxShadow(paintInfo, paintRect, style, Inset);
189 194
190 // The theme will tell us whether or not we should also paint the CSS border . 195 // The theme will tell us whether or not we should also paint the CSS
196 // border.
191 if (boxDecorationData.hasBorderDecoration && 197 if (boxDecorationData.hasBorderDecoration &&
192 (!boxDecorationData.hasAppearance || 198 (!boxDecorationData.hasAppearance ||
193 (!themePainted && 199 (!themePainted &&
194 LayoutTheme::theme().painter().paintBorderOnly(m_layoutBox, paintInfo, 200 LayoutTheme::theme().painter().paintBorderOnly(m_layoutBox, paintInfo,
195 snappedPaintRect))) && 201 snappedPaintRect))) &&
196 !(m_layoutBox.isTable() && 202 !(m_layoutBox.isTable() &&
197 toLayoutTable(&m_layoutBox)->collapseBorders())) { 203 toLayoutTable(&m_layoutBox)->collapseBorders())) {
198 paintBorder(m_layoutBox, paintInfo, paintRect, style, 204 paintBorder(m_layoutBox, paintInfo, paintRect, style,
199 boxDecorationData.bleedAvoidance); 205 boxDecorationData.bleedAvoidance);
200 } 206 }
(...skipping 19 matching lines...) Expand all
220 } 226 }
221 227
222 bool BoxPainter::calculateFillLayerOcclusionCulling( 228 bool BoxPainter::calculateFillLayerOcclusionCulling(
223 FillLayerOcclusionOutputList& reversedPaintList, 229 FillLayerOcclusionOutputList& reversedPaintList,
224 const FillLayer& fillLayer) { 230 const FillLayer& fillLayer) {
225 bool isNonAssociative = false; 231 bool isNonAssociative = false;
226 for (auto currentLayer = &fillLayer; currentLayer; 232 for (auto currentLayer = &fillLayer; currentLayer;
227 currentLayer = currentLayer->next()) { 233 currentLayer = currentLayer->next()) {
228 reversedPaintList.append(currentLayer); 234 reversedPaintList.append(currentLayer);
229 // Stop traversal when an opaque layer is encountered. 235 // Stop traversal when an opaque layer is encountered.
230 // FIXME : It would be possible for the following occlusion culling test to be more aggressive 236 // FIXME : It would be possible for the following occlusion culling test to
231 // on layers with no repeat by testing whether the image covers the layout r ect. 237 // be more aggressive on layers with no repeat by testing whether the image
232 // Testing that here would imply duplicating a lot of calculations that are currently done in 238 // covers the layout rect. Testing that here would imply duplicating a lot
233 // LayoutBoxModelObject::paintFillLayer. A more efficient solution might be to move the layer 239 // of calculations that are currently done in
234 // recursion into paintFillLayer, or to compute the layer geometry here and pass it down. 240 // LayoutBoxModelObject::paintFillLayer. A more efficient solution might be
241 // to move the layer recursion into paintFillLayer, or to compute the layer
242 // geometry here and pass it down.
235 243
236 // TODO(trchen): Need to check compositing mode as well. 244 // TODO(trchen): Need to check compositing mode as well.
237 if (currentLayer->blendMode() != WebBlendModeNormal) 245 if (currentLayer->blendMode() != WebBlendModeNormal)
238 isNonAssociative = true; 246 isNonAssociative = true;
239 247
240 // TODO(trchen): A fill layer cannot paint if the calculated tile size is em pty. 248 // TODO(trchen): A fill layer cannot paint if the calculated tile size is
241 // This occlusion check can be wrong. 249 // empty. This occlusion check can be wrong.
242 if (currentLayer->clipOccludesNextLayers() && 250 if (currentLayer->clipOccludesNextLayers() &&
243 currentLayer->imageOccludesNextLayers(m_layoutBox)) { 251 currentLayer->imageOccludesNextLayers(m_layoutBox)) {
244 if (currentLayer->clip() == BorderFillBox) 252 if (currentLayer->clip() == BorderFillBox)
245 isNonAssociative = false; 253 isNonAssociative = false;
246 break; 254 break;
247 } 255 }
248 } 256 }
249 return isNonAssociative; 257 return isNonAssociative;
250 } 258 }
251 259
252 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, 260 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo,
253 const Color& c, 261 const Color& c,
254 const FillLayer& fillLayer, 262 const FillLayer& fillLayer,
255 const LayoutRect& rect, 263 const LayoutRect& rect,
256 BackgroundBleedAvoidance bleedAvoidance, 264 BackgroundBleedAvoidance bleedAvoidance,
257 SkXfermode::Mode op, 265 SkXfermode::Mode op,
258 const LayoutObject* backgroundObject) { 266 const LayoutObject* backgroundObject) {
259 // TODO(trchen): Box shadow optimization and background color are concepts tha t only 267 // TODO(trchen): Box shadow optimization and background color are concepts
260 // apply to background layers. Ideally we should refactor those out of paintFi llLayer. 268 // that only apply to background layers. Ideally we should refactor those out
269 // of paintFillLayer.
261 FillLayerOcclusionOutputList reversedPaintList; 270 FillLayerOcclusionOutputList reversedPaintList;
262 bool shouldDrawBackgroundInSeparateBuffer = false; 271 bool shouldDrawBackgroundInSeparateBuffer = false;
263 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) { 272 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) {
264 shouldDrawBackgroundInSeparateBuffer = 273 shouldDrawBackgroundInSeparateBuffer =
265 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer); 274 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer);
266 } else { 275 } else {
267 // If we are responsible for painting box shadow, don't perform fill layer c ulling. 276 // If we are responsible for painting box shadow, don't perform fill layer
268 // TODO(trchen): In theory we only need to make sure the last layer has bord er box clipping 277 // culling.
269 // and make it paint the box shadow. Investigate optimization opportunity la ter. 278 // TODO(trchen): In theory we only need to make sure the last layer has
279 // border box clipping and make it paint the box shadow. Investigate
280 // optimization opportunity later.
270 for (auto currentLayer = &fillLayer; currentLayer; 281 for (auto currentLayer = &fillLayer; currentLayer;
271 currentLayer = currentLayer->next()) { 282 currentLayer = currentLayer->next()) {
272 reversedPaintList.append(currentLayer); 283 reversedPaintList.append(currentLayer);
273 if (currentLayer->composite() != CompositeSourceOver || 284 if (currentLayer->composite() != CompositeSourceOver ||
274 currentLayer->blendMode() != WebBlendModeNormal) 285 currentLayer->blendMode() != WebBlendModeNormal)
275 shouldDrawBackgroundInSeparateBuffer = true; 286 shouldDrawBackgroundInSeparateBuffer = true;
276 } 287 }
277 } 288 }
278 289
279 // TODO(trchen): We can optimize out isolation group if we have a non-transpar ent 290 // TODO(trchen): We can optimize out isolation group if we have a
280 // background color and the bottom layer encloses all other layers. 291 // non-transparent background color and the bottom layer encloses all other
292 // layers.
281 293
282 GraphicsContext& context = paintInfo.context; 294 GraphicsContext& context = paintInfo.context;
283 295
284 if (shouldDrawBackgroundInSeparateBuffer) 296 if (shouldDrawBackgroundInSeparateBuffer)
285 context.beginLayer(); 297 context.beginLayer();
286 298
287 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); 299 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend();
288 ++it) 300 ++it)
289 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0, 301 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0,
290 LayoutSize(), op, backgroundObject); 302 LayoutSize(), op, backgroundObject);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 359
348 FloatRoundedRect backgroundRoundedRectAdjustedForBleedAvoidance( 360 FloatRoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(
349 const LayoutObject& obj, 361 const LayoutObject& obj,
350 const LayoutRect& borderRect, 362 const LayoutRect& borderRect,
351 BackgroundBleedAvoidance bleedAvoidance, 363 BackgroundBleedAvoidance bleedAvoidance,
352 const InlineFlowBox* box, 364 const InlineFlowBox* box,
353 const LayoutSize& boxSize, 365 const LayoutSize& boxSize,
354 bool includeLogicalLeftEdge, 366 bool includeLogicalLeftEdge,
355 bool includeLogicalRightEdge) { 367 bool includeLogicalRightEdge) {
356 if (bleedAvoidance == BackgroundBleedShrinkBackground) { 368 if (bleedAvoidance == BackgroundBleedShrinkBackground) {
357 // Inset the background rect by a "safe" amount: 1/2 border-width for opaque border styles, 369 // Inset the background rect by a "safe" amount: 1/2 border-width for opaque
358 // 1/6 border-width for double borders. 370 // border styles, 1/6 border-width for double borders.
359 371
360 // TODO(fmalita): we should be able to fold these parameters into BoxBorderI nfo or 372 // TODO(fmalita): we should be able to fold these parameters into
361 // BoxDecorationData and avoid calling getBorderEdgeInfo redundantly here. 373 // BoxBorderInfo or BoxDecorationData and avoid calling getBorderEdgeInfo
374 // redundantly here.
362 BorderEdge edges[4]; 375 BorderEdge edges[4];
363 obj.style()->getBorderEdgeInfo(edges, includeLogicalLeftEdge, 376 obj.style()->getBorderEdgeInfo(edges, includeLogicalLeftEdge,
364 includeLogicalRightEdge); 377 includeLogicalRightEdge);
365 378
366 // Use the most conservative inset to avoid mixed-style corner issues. 379 // Use the most conservative inset to avoid mixed-style corner issues.
367 float fractionalInset = 1.0f / 2; 380 float fractionalInset = 1.0f / 2;
368 for (auto& edge : edges) { 381 for (auto& edge : edges) {
369 if (edge.borderStyle() == BorderStyleDouble) { 382 if (edge.borderStyle() == BorderStyleDouble) {
370 fractionalInset = 1.0f / 6; 383 fractionalInset = 1.0f / 6;
371 break; 384 break;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 color(bgColor), 418 color(bgColor),
406 includeLeftEdge(box ? box->includeLogicalLeftEdge() : true), 419 includeLeftEdge(box ? box->includeLogicalLeftEdge() : true),
407 includeRightEdge(box ? box->includeLogicalRightEdge() : true), 420 includeRightEdge(box ? box->includeLogicalRightEdge() : true),
408 isBottomLayer(!layer.next()), 421 isBottomLayer(!layer.next()),
409 isBorderFill(layer.clip() == BorderFillBox), 422 isBorderFill(layer.clip() == BorderFillBox),
410 isClippedWithLocalScrolling(obj.hasOverflowClip() && 423 isClippedWithLocalScrolling(obj.hasOverflowClip() &&
411 layer.attachment() == 424 layer.attachment() ==
412 LocalBackgroundAttachment) { 425 LocalBackgroundAttachment) {
413 // When printing backgrounds is disabled or using economy mode, 426 // When printing backgrounds is disabled or using economy mode,
414 // change existing background colors and images to a solid white background. 427 // change existing background colors and images to a solid white background.
415 // If there's no bg color or image, leave it untouched to avoid affecting tr ansparency. 428 // If there's no bg color or image, leave it untouched to avoid affecting
416 // We don't try to avoid loading the background images, because this style f lag is only set 429 // transparency. We don't try to avoid loading the background images,
417 // when printing, and at that point we've already loaded the background imag es anyway. (To avoid 430 // because this style flag is only set when printing, and at that point
418 // loading the background images we'd have to do this check when applying st yles rather than 431 // we've already loaded the background images anyway. (To avoid loading the
419 // while layout.) 432 // background images we'd have to do this check when applying styles rather
433 // than while layout.)
420 if (BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(obj.styleRef(), 434 if (BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(obj.styleRef(),
421 obj.document())) { 435 obj.document())) {
422 // Note that we can't reuse this variable below because the bgColor might be changed 436 // Note that we can't reuse this variable below because the bgColor might
437 // be changed.
423 bool shouldPaintBackgroundColor = isBottomLayer && color.alpha(); 438 bool shouldPaintBackgroundColor = isBottomLayer && color.alpha();
424 if (image || shouldPaintBackgroundColor) { 439 if (image || shouldPaintBackgroundColor) {
425 color = Color::white; 440 color = Color::white;
426 image = nullptr; 441 image = nullptr;
427 } 442 }
428 } 443 }
429 444
430 const bool hasRoundedBorder = 445 const bool hasRoundedBorder =
431 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge); 446 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge);
432 // BorderFillBox radius clipping is taken care of by BackgroundBleedClip{Onl y,Layer} 447 // BorderFillBox radius clipping is taken care of by
448 // BackgroundBleedClip{Only,Layer}
433 isRoundedFill = hasRoundedBorder && 449 isRoundedFill = hasRoundedBorder &&
434 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance)); 450 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance));
435 451
436 shouldPaintImage = image && image->canRender(); 452 shouldPaintImage = image && image->canRender();
437 shouldPaintColor = 453 shouldPaintColor =
438 isBottomLayer && color.alpha() && 454 isBottomLayer && color.alpha() &&
439 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj)); 455 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj));
440 shouldPaintShadow = 456 shouldPaintShadow =
441 shouldPaintColor && 457 shouldPaintColor &&
442 obj.boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); 458 obj.boxShadowShouldBeAppliedToBackground(bleedAvoidance, box);
443 } 459 }
444 460
445 // FillLayerInfo is a temporary, stack-allocated container which cannot outliv e the StyleImage. 461 // FillLayerInfo is a temporary, stack-allocated container which cannot
446 // This would normally be a raw pointer, if not for the Oilpan tooling complai nts. 462 // outlive the StyleImage. This would normally be a raw pointer, if not for
463 // the Oilpan tooling complaints.
447 Member<StyleImage> image; 464 Member<StyleImage> image;
448 Color color; 465 Color color;
449 466
450 bool includeLeftEdge; 467 bool includeLeftEdge;
451 bool includeRightEdge; 468 bool includeRightEdge;
452 bool isBottomLayer; 469 bool isBottomLayer;
453 bool isBorderFill; 470 bool isBorderFill;
454 bool isClippedWithLocalScrolling; 471 bool isClippedWithLocalScrolling;
455 bool isRoundedFill; 472 bool isRoundedFill;
456 473
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 Optional<BackgroundImageGeometry>& geometry) { 539 Optional<BackgroundImageGeometry>& geometry) {
523 // Complex cases not handled on the fast path. 540 // Complex cases not handled on the fast path.
524 if (!info.isBottomLayer || !info.isBorderFill || 541 if (!info.isBottomLayer || !info.isBorderFill ||
525 info.isClippedWithLocalScrolling) 542 info.isClippedWithLocalScrolling)
526 return false; 543 return false;
527 544
528 // Transparent layer, nothing to paint. 545 // Transparent layer, nothing to paint.
529 if (!info.shouldPaintColor && !info.shouldPaintImage) 546 if (!info.shouldPaintColor && !info.shouldPaintImage)
530 return true; 547 return true;
531 548
532 // When the layer has an image, figure out whether it is covered by a single t ile. 549 // When the layer has an image, figure out whether it is covered by a single
550 // tile.
533 FloatRect imageTile; 551 FloatRect imageTile;
534 if (info.shouldPaintImage) { 552 if (info.shouldPaintImage) {
535 DCHECK(!geometry); 553 DCHECK(!geometry);
536 geometry.emplace(); 554 geometry.emplace();
537 geometry->calculate(obj, paintInfo.paintContainer(), 555 geometry->calculate(obj, paintInfo.paintContainer(),
538 paintInfo.getGlobalPaintFlags(), layer, rect); 556 paintInfo.getGlobalPaintFlags(), layer, rect);
539 557
540 if (!geometry->destRect().isEmpty()) { 558 if (!geometry->destRect().isEmpty()) {
541 // The tile is too small. 559 // The tile is too small.
542 if (geometry->tileSize().width() < rect.width() || 560 if (geometry->tileSize().width() < rect.width() ||
543 geometry->tileSize().height() < rect.height()) 561 geometry->tileSize().height() < rect.height())
544 return false; 562 return false;
545 563
546 imageTile = Image::computeTileContaining( 564 imageTile = Image::computeTileContaining(
547 FloatPoint(geometry->destRect().location()), 565 FloatPoint(geometry->destRect().location()),
548 FloatSize(geometry->tileSize()), FloatPoint(geometry->phase()), 566 FloatSize(geometry->tileSize()), FloatPoint(geometry->phase()),
549 FloatSize(geometry->spaceSize())); 567 FloatSize(geometry->spaceSize()));
550 568
551 // The tile is misaligned. 569 // The tile is misaligned.
552 if (!imageTile.contains(FloatRect(rect))) 570 if (!imageTile.contains(FloatRect(rect)))
553 return false; 571 return false;
554 } 572 }
555 } 573 }
556 574
557 // At this point we're committed to the fast path: the destination (r)rect fit s within a single 575 // At this point we're committed to the fast path: the destination (r)rect
558 // tile, and we can paint it using direct draw(R)Rect() calls. 576 // fits within a single tile, and we can paint it using direct draw(R)Rect()
577 // calls.
559 GraphicsContext& context = paintInfo.context; 578 GraphicsContext& context = paintInfo.context;
560 FloatRoundedRect border = 579 FloatRoundedRect border =
561 info.isRoundedFill ? backgroundRoundedRectAdjustedForBleedAvoidance( 580 info.isRoundedFill ? backgroundRoundedRectAdjustedForBleedAvoidance(
562 obj, rect, bleedAvoidance, box, boxSize, 581 obj, rect, bleedAvoidance, box, boxSize,
563 info.includeLeftEdge, info.includeRightEdge) 582 info.includeLeftEdge, info.includeRightEdge)
564 : FloatRoundedRect(pixelSnappedIntRect(rect)); 583 : FloatRoundedRect(pixelSnappedIntRect(rect));
565 584
566 Optional<RoundedInnerRectClipper> clipper; 585 Optional<RoundedInnerRectClipper> clipper;
567 if (info.isRoundedFill && !border.isRenderable()) { 586 if (info.isRoundedFill && !border.isRenderable()) {
568 // When the rrect is not renderable, we resort to clipping. 587 // When the rrect is not renderable, we resort to clipping.
569 // RoundedInnerRectClipper handles this case via discrete, corner-wise clipp ing. 588 // RoundedInnerRectClipper handles this case via discrete, corner-wise
589 // clipping.
570 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext); 590 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext);
571 border.setRadii(FloatRoundedRect::Radii()); 591 border.setRadii(FloatRoundedRect::Radii());
572 } 592 }
573 593
574 // Paint the color + shadow if needed. 594 // Paint the color + shadow if needed.
575 if (info.shouldPaintColor) { 595 if (info.shouldPaintColor) {
576 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); 596 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow);
577 context.fillRoundedRect(border, info.color); 597 context.fillRoundedRect(border, info.color);
578 } 598 }
579 599
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 context, info.isClippedWithLocalScrolling); 687 context, info.isClippedWithLocalScrolling);
668 LayoutRect scrolledPaintRect = rect; 688 LayoutRect scrolledPaintRect = rect;
669 if (info.isClippedWithLocalScrolling && 689 if (info.isClippedWithLocalScrolling &&
670 !isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( 690 !isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
671 &obj, paintInfo)) { 691 &obj, paintInfo)) {
672 // Clip to the overflow area. 692 // Clip to the overflow area.
673 const LayoutBox& thisBox = toLayoutBox(obj); 693 const LayoutBox& thisBox = toLayoutBox(obj);
674 // TODO(chrishtr): this should be pixel-snapped. 694 // TODO(chrishtr): this should be pixel-snapped.
675 context.clip(FloatRect(thisBox.overflowClipRect(rect.location()))); 695 context.clip(FloatRect(thisBox.overflowClipRect(rect.location())));
676 696
677 // Adjust the paint rect to reflect a scrolled content box with borders at t he ends. 697 // Adjust the paint rect to reflect a scrolled content box with borders at
698 // the ends.
678 IntSize offset = thisBox.scrolledContentOffset(); 699 IntSize offset = thisBox.scrolledContentOffset();
679 scrolledPaintRect.move(-offset); 700 scrolledPaintRect.move(-offset);
680 scrolledPaintRect.setWidth(bLeft + thisBox.scrollWidth() + bRight); 701 scrolledPaintRect.setWidth(bLeft + thisBox.scrollWidth() + bRight);
681 scrolledPaintRect.setHeight(thisBox.borderTop() + thisBox.scrollHeight() + 702 scrolledPaintRect.setHeight(thisBox.borderTop() + thisBox.scrollHeight() +
682 thisBox.borderBottom()); 703 thisBox.borderBottom());
683 } 704 }
684 705
685 GraphicsContextStateSaver backgroundClipStateSaver(context, false); 706 GraphicsContextStateSaver backgroundClipStateSaver(context, false);
686 IntRect maskRect; 707 IntRect maskRect;
687 708
(...skipping 15 matching lines...) Expand all
703 scrolledPaintRect.height() - obj.borderTop() - obj.borderBottom() - 724 scrolledPaintRect.height() - obj.borderTop() - obj.borderBottom() -
704 (includePadding ? obj.paddingTop() + obj.paddingBottom() 725 (includePadding ? obj.paddingTop() + obj.paddingBottom()
705 : LayoutUnit())); 726 : LayoutUnit()));
706 backgroundClipStateSaver.save(); 727 backgroundClipStateSaver.save();
707 // TODO(chrishtr): this should be pixel-snapped. 728 // TODO(chrishtr): this should be pixel-snapped.
708 context.clip(FloatRect(clipRect)); 729 context.clip(FloatRect(clipRect));
709 730
710 break; 731 break;
711 } 732 }
712 case TextFillBox: { 733 case TextFillBox: {
713 // First figure out how big the mask has to be. It should be no bigger tha n what we need 734 // First figure out how big the mask has to be. It should be no bigger
714 // to actually render, so we should intersect the dirty rect with the bord er box of the background. 735 // than what we need to actually render, so we should intersect the dirty
736 // rect with the border box of the background.
715 maskRect = pixelSnappedIntRect(rect); 737 maskRect = pixelSnappedIntRect(rect);
716 738
717 // We draw the background into a separate layer, to be later masked with y et another layer 739 // We draw the background into a separate layer, to be later masked with
718 // holding the text content. 740 // yet another layer holding the text content.
719 backgroundClipStateSaver.save(); 741 backgroundClipStateSaver.save();
720 context.clip(maskRect); 742 context.clip(maskRect);
721 context.beginLayer(); 743 context.beginLayer();
722 744
723 break; 745 break;
724 } 746 }
725 case BorderFillBox: 747 case BorderFillBox:
726 break; 748 break;
727 default: 749 default:
728 ASSERT_NOT_REACHED(); 750 ASSERT_NOT_REACHED();
729 break; 751 break;
730 } 752 }
731 753
732 // Paint the color first underneath all images, culled if background image occ ludes it. 754 // Paint the color first underneath all images, culled if background image
733 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the cull ing test 755 // occludes it.
734 // by verifying whether the background image covers the entire painting area. 756 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the
757 // culling test by verifying whether the background image covers the entire
758 // painting area.
735 if (info.isBottomLayer && info.color.alpha()) { 759 if (info.isBottomLayer && info.color.alpha()) {
736 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); 760 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
737 if (info.shouldPaintColor || info.shouldPaintShadow) { 761 if (info.shouldPaintColor || info.shouldPaintShadow) {
738 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); 762 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow);
739 context.fillRect(backgroundRect, info.color); 763 context.fillRect(backgroundRect, info.color);
740 } 764 }
741 } 765 }
742 766
743 // no progressive loading of the background image 767 // no progressive loading of the background image
744 if (info.shouldPaintImage) { 768 if (info.shouldPaintImage) {
(...skipping 18 matching lines...) Expand all
763 imageContext.image(), FloatRect(geometry->destRect()), 787 imageContext.image(), FloatRect(geometry->destRect()),
764 FloatPoint(geometry->phase()), FloatSize(geometry->tileSize()), 788 FloatPoint(geometry->phase()), FloatSize(geometry->tileSize()),
765 imageContext.compositeOp(), FloatSize(geometry->spaceSize())); 789 imageContext.compositeOp(), FloatSize(geometry->spaceSize()));
766 } 790 }
767 } 791 }
768 792
769 if (bgLayer.clip() == TextFillBox) { 793 if (bgLayer.clip() == TextFillBox) {
770 // Create the text mask layer. 794 // Create the text mask layer.
771 context.beginLayer(1, SkXfermode::kDstIn_Mode); 795 context.beginLayer(1, SkXfermode::kDstIn_Mode);
772 796
773 // Now draw the text into the mask. We do this by painting using a special p aint phase that signals to 797 // Now draw the text into the mask. We do this by painting using a special
798 // paint phase that signals to
774 // InlineTextBoxes that they should just add their contents to the clip. 799 // InlineTextBoxes that they should just add their contents to the clip.
775 PaintInfo info(context, maskRect, PaintPhaseTextClip, 800 PaintInfo info(context, maskRect, PaintPhaseTextClip,
776 GlobalPaintNormalPhase, 0); 801 GlobalPaintNormalPhase, 0);
777 if (box) { 802 if (box) {
778 const RootInlineBox& root = box->root(); 803 const RootInlineBox& root = box->root();
779 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), 804 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(),
780 scrolledPaintRect.y() - box->y()), 805 scrolledPaintRect.y() - box->y()),
781 root.lineTop(), root.lineBottom()); 806 root.lineTop(), root.lineBottom());
782 } else { 807 } else {
783 // FIXME: this should only have an effect for the line box list within |ob j|. Change this to create a LineBoxListPainter directly. 808 // FIXME: this should only have an effect for the line box list within
809 // |obj|. Change this to create a LineBoxListPainter directly.
784 LayoutSize localOffset = 810 LayoutSize localOffset =
785 obj.isBox() ? toLayoutBox(&obj)->locationOffset() : LayoutSize(); 811 obj.isBox() ? toLayoutBox(&obj)->locationOffset() : LayoutSize();
786 obj.paint(info, scrolledPaintRect.location() - localOffset); 812 obj.paint(info, scrolledPaintRect.location() - localOffset);
787 } 813 }
788 814
789 context.endLayer(); 815 context.endLayer();
790 context.endLayer(); 816 context.endLayer();
791 } 817 }
792 } 818 }
793 819
(...skipping 25 matching lines...) Expand all
819 bool flattenCompositingLayers = 845 bool flattenCompositingLayers =
820 paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers; 846 paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers;
821 847
822 bool allMaskImagesLoaded = true; 848 bool allMaskImagesLoaded = true;
823 849
824 if (!compositedMask || flattenCompositingLayers) { 850 if (!compositedMask || flattenCompositingLayers) {
825 pushTransparencyLayer = true; 851 pushTransparencyLayer = true;
826 StyleImage* maskBoxImage = m_layoutBox.style()->maskBoxImage().image(); 852 StyleImage* maskBoxImage = m_layoutBox.style()->maskBoxImage().image();
827 const FillLayer& maskLayers = m_layoutBox.style()->maskLayers(); 853 const FillLayer& maskLayers = m_layoutBox.style()->maskLayers();
828 854
829 // Don't render a masked element until all the mask images have loaded, to p revent a flash of unmasked content. 855 // Don't render a masked element until all the mask images have loaded, to
856 // prevent a flash of unmasked content.
830 if (maskBoxImage) 857 if (maskBoxImage)
831 allMaskImagesLoaded &= maskBoxImage->isLoaded(); 858 allMaskImagesLoaded &= maskBoxImage->isLoaded();
832 859
833 allMaskImagesLoaded &= maskLayers.imagesAreLoaded(); 860 allMaskImagesLoaded &= maskLayers.imagesAreLoaded();
834 861
835 paintInfo.context.beginLayer(1, SkXfermode::kDstIn_Mode); 862 paintInfo.context.beginLayer(1, SkXfermode::kDstIn_Mode);
836 } 863 }
837 864
838 if (allMaskImagesLoaded) { 865 if (allMaskImagesLoaded) {
839 paintFillLayers(paintInfo, Color::transparent, 866 paintFillLayers(paintInfo, Color::transparent,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 includeLogicalRightEdge); 932 includeLogicalRightEdge);
906 borderPainter.paintBorder(info, rect); 933 borderPainter.paintBorder(info, rect);
907 } 934 }
908 935
909 void BoxPainter::paintBoxShadow(const PaintInfo& info, 936 void BoxPainter::paintBoxShadow(const PaintInfo& info,
910 const LayoutRect& paintRect, 937 const LayoutRect& paintRect,
911 const ComputedStyle& style, 938 const ComputedStyle& style,
912 ShadowStyle shadowStyle, 939 ShadowStyle shadowStyle,
913 bool includeLogicalLeftEdge, 940 bool includeLogicalLeftEdge,
914 bool includeLogicalRightEdge) { 941 bool includeLogicalRightEdge) {
915 // FIXME: Deal with border-image. Would be great to use border-image as a mask . 942 // FIXME: Deal with border-image. Would be great to use border-image as a
943 // mask.
916 GraphicsContext& context = info.context; 944 GraphicsContext& context = info.context;
917 if (!style.boxShadow()) 945 if (!style.boxShadow())
918 return; 946 return;
919 FloatRoundedRect border = 947 FloatRoundedRect border =
920 (shadowStyle == Inset) 948 (shadowStyle == Inset)
921 ? style.getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, 949 ? style.getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge,
922 includeLogicalRightEdge) 950 includeLogicalRightEdge)
923 : style.getRoundedBorderFor(paintRect, includeLogicalLeftEdge, 951 : style.getRoundedBorderFor(paintRect, includeLogicalLeftEdge,
924 includeLogicalRightEdge); 952 includeLogicalRightEdge);
925 953
(...skipping 30 matching lines...) Expand all
956 shadowRect.inflate(shadowBlur + shadowSpread); 984 shadowRect.inflate(shadowBlur + shadowSpread);
957 shadowRect.move(shadowOffset); 985 shadowRect.move(shadowOffset);
958 986
959 // Save the state and clip, if not already done. 987 // Save the state and clip, if not already done.
960 // The clip does not depend on any shadow-specific properties. 988 // The clip does not depend on any shadow-specific properties.
961 if (!stateSaver.saved()) { 989 if (!stateSaver.saved()) {
962 stateSaver.save(); 990 stateSaver.save();
963 if (hasBorderRadius) { 991 if (hasBorderRadius) {
964 FloatRoundedRect rectToClipOut = border; 992 FloatRoundedRect rectToClipOut = border;
965 993
966 // If the box is opaque, it is unnecessary to clip it out. However, do ing so saves time 994 // If the box is opaque, it is unnecessary to clip it out. However,
967 // when painting the shadow. On the other hand, it introduces subpixel gaps along the 995 // doing so saves time when painting the shadow. On the other hand, it
968 // corners. Those are avoided by insetting the clipping path by one CS S pixel. 996 // introduces subpixel gaps along the corners. Those are avoided by
997 // insetting the clipping path by one CSS pixel.
969 if (hasOpaqueBackground) 998 if (hasOpaqueBackground)
970 rectToClipOut.inflateWithRadii(-1); 999 rectToClipOut.inflateWithRadii(-1);
971 1000
972 if (!rectToClipOut.isEmpty()) 1001 if (!rectToClipOut.isEmpty())
973 context.clipOutRoundedRect(rectToClipOut); 1002 context.clipOutRoundedRect(rectToClipOut);
974 } else { 1003 } else {
975 // This IntRect is correct even with fractional shadows, because it is used for the rectangle 1004 // This IntRect is correct even with fractional shadows, because it is
976 // of the box itself, which is always pixel-aligned. 1005 // used for the rectangle of the box itself, which is always
1006 // pixel-aligned.
977 FloatRect rectToClipOut = border.rect(); 1007 FloatRect rectToClipOut = border.rect();
978 1008
979 // If the box is opaque, it is unnecessary to clip it out. However, do ing so saves time 1009 // If the box is opaque, it is unnecessary to clip it out. However,
980 // when painting the shadow. On the other hand, it introduces subpixel gaps along the 1010 // doing so saves time when painting the shadow. On the other hand, it
981 // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path 1011 // introduces subpixel gaps along the edges if they are not
982 // by one CSS pixel. 1012 // pixel-aligned. Those are avoided by insetting the clipping path by
1013 // one CSS pixel.
983 if (hasOpaqueBackground) 1014 if (hasOpaqueBackground)
984 rectToClipOut.inflate(-1); 1015 rectToClipOut.inflate(-1);
985 1016
986 if (!rectToClipOut.isEmpty()) 1017 if (!rectToClipOut.isEmpty())
987 context.clipOut(rectToClipOut); 1018 context.clipOut(rectToClipOut);
988 } 1019 }
989 } 1020 }
990 1021
991 // Draw only the shadow. 1022 // Draw only the shadow.
992 context.setShadow(shadowOffset, shadowBlur, shadowColor, 1023 context.setShadow(shadowOffset, shadowBlur, shadowColor,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy( 1071 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(
1041 const ComputedStyle& style, 1072 const ComputedStyle& style,
1042 const Document& document) { 1073 const Document& document) {
1043 return document.printing() && 1074 return document.printing() &&
1044 style.getPrintColorAdjust() == PrintColorAdjustEconomy && 1075 style.getPrintColorAdjust() == PrintColorAdjustEconomy &&
1045 (!document.settings() || 1076 (!document.settings() ||
1046 !document.settings()->shouldPrintBackgrounds()); 1077 !document.settings()->shouldPrintBackgrounds());
1047 } 1078 }
1048 1079
1049 } // namespace blink 1080 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/paint/BoxPainter.h ('k') | third_party/WebKit/Source/core/paint/ClipPathClipper.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698