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

Side by Side Diff: Source/core/rendering/RenderBoxModelObject.cpp

Issue 559733005: Move painting code from RenderBoxModelObject into BoxPainter. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 3 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved. 7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either 11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version. 12 * version 2 of the License, or (at your option) any later version.
13 * 13 *
14 * This library is distributed in the hope that it will be useful, 14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details. 17 * Library General Public License for more details.
18 * 18 *
19 * You should have received a copy of the GNU Library General Public License 19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to 20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA. 22 * Boston, MA 02110-1301, USA.
23 * 23 *
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/rendering/RenderBoxModelObject.h" 27 #include "core/rendering/RenderBoxModelObject.h"
28 28
29 #include "core/HTMLNames.h"
30 #include "core/frame/Settings.h"
31 #include "core/html/HTMLFrameOwnerElement.h"
32 #include "core/page/scrolling/ScrollingConstraints.h" 29 #include "core/page/scrolling/ScrollingConstraints.h"
33 #include "core/rendering/ImageQualityController.h" 30 #include "core/rendering/ImageQualityController.h"
34 #include "core/rendering/RenderBlock.h" 31 #include "core/rendering/RenderBlock.h"
35 #include "core/rendering/RenderFlowThread.h" 32 #include "core/rendering/RenderFlowThread.h"
36 #include "core/rendering/RenderGeometryMap.h" 33 #include "core/rendering/RenderGeometryMap.h"
37 #include "core/rendering/RenderInline.h" 34 #include "core/rendering/RenderInline.h"
38 #include "core/rendering/RenderLayer.h" 35 #include "core/rendering/RenderLayer.h"
39 #include "core/rendering/RenderObjectInlines.h" 36 #include "core/rendering/RenderObjectInlines.h"
40 #include "core/rendering/RenderRegion.h" 37 #include "core/rendering/RenderRegion.h"
41 #include "core/rendering/RenderTextFragment.h" 38 #include "core/rendering/RenderTextFragment.h"
42 #include "core/rendering/RenderView.h" 39 #include "core/rendering/RenderView.h"
43 #include "core/rendering/compositing/CompositedLayerMapping.h" 40 #include "core/rendering/compositing/CompositedLayerMapping.h"
44 #include "core/rendering/compositing/RenderLayerCompositor.h" 41 #include "core/rendering/compositing/RenderLayerCompositor.h"
45 #include "core/rendering/style/BorderEdge.h" 42 #include "core/rendering/style/BorderEdge.h"
46 #include "core/rendering/style/ShadowList.h" 43 #include "core/rendering/style/ShadowList.h"
47 #include "platform/LengthFunctions.h" 44 #include "platform/LengthFunctions.h"
48 #include "platform/geometry/TransformState.h" 45 #include "platform/geometry/TransformState.h"
49 #include "platform/graphics/DrawLooperBuilder.h" 46 #include "platform/graphics/DrawLooperBuilder.h"
50 #include "platform/graphics/GraphicsContextStateSaver.h" 47 #include "platform/graphics/GraphicsContextStateSaver.h"
51 #include "platform/graphics/Path.h" 48 #include "platform/graphics/Path.h"
52 #include "wtf/CurrentTime.h" 49 #include "wtf/CurrentTime.h"
53 50
54 namespace blink { 51 namespace blink {
55 52
56 using namespace HTMLNames;
57
58 // The HashMap for storing continuation pointers. 53 // The HashMap for storing continuation pointers.
59 // An inline can be split with blocks occuring in between the inline content. 54 // An inline can be split with blocks occuring in between the inline content.
60 // When this occurs we need a pointer to the next object. We can basically be 55 // When this occurs we need a pointer to the next object. We can basically be
61 // split into a sequence of inlines and blocks. The continuation will either be 56 // split into a sequence of inlines and blocks. The continuation will either be
62 // an anonymous block (that houses other blocks) or it will be an inline flow. 57 // an anonymous block (that houses other blocks) or it will be an inline flow.
63 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as 58 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
64 // its continuation but the <b> will just have an inline as its continuation. 59 // its continuation but the <b> will just have an inline as its continuation.
65 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtr WillBeMember<RenderBoxModelObject> > ContinuationMap; 60 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtr WillBeMember<RenderBoxModelObject> > ContinuationMap;
66 static OwnPtrWillBePersistent<ContinuationMap>* continuationMap = 0; 61 static OwnPtrWillBePersistent<ContinuationMap>* continuationMap = 0;
67 62
(...skipping 27 matching lines...) Expand all
95 return; 90 return;
96 91
97 layer()->contentChanged(changeType); 92 layer()->contentChanged(changeType);
98 } 93 }
99 94
100 bool RenderBoxModelObject::hasAcceleratedCompositing() const 95 bool RenderBoxModelObject::hasAcceleratedCompositing() const
101 { 96 {
102 return view()->compositor()->hasAcceleratedCompositing(); 97 return view()->compositor()->hasAcceleratedCompositing();
103 } 98 }
104 99
105 InterpolationQuality RenderBoxModelObject::chooseInterpolationQuality(GraphicsCo ntext* context, Image* image, const void* layer, const LayoutSize& size)
106 {
107 return ImageQualityController::imageQualityController()->chooseInterpolation Quality(context, this, image, layer, size);
108 }
109
110 RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node) 100 RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node)
111 : RenderLayerModelObject(node) 101 : RenderLayerModelObject(node)
112 { 102 {
113 } 103 }
114 104
115 RenderBoxModelObject::~RenderBoxModelObject() 105 RenderBoxModelObject::~RenderBoxModelObject()
116 { 106 {
117 } 107 }
118 108
119 void RenderBoxModelObject::willBeDestroyed() 109 void RenderBoxModelObject::willBeDestroyed()
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 if (cb->isRenderView()) 185 if (cb->isRenderView())
196 return false; 186 return false;
197 187
198 if (cb->isOutOfFlowPositioned() && !cb->style()->logicalTop().isAuto() && !c b->style()->logicalBottom().isAuto()) 188 if (cb->isOutOfFlowPositioned() && !cb->style()->logicalTop().isAuto() && !c b->style()->logicalBottom().isAuto())
199 return false; 189 return false;
200 190
201 // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'. 191 // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'.
202 return cb->hasAutoHeightOrContainingBlockWithAutoHeight(); 192 return cb->hasAutoHeightOrContainingBlockWithAutoHeight();
203 } 193 }
204 194
205 bool RenderBoxModelObject::isDocumentElementWithOpaqueBackground() const
206 {
207 if (!isDocumentElement())
208 return false;
209
210 // The background is opaque only if we're the root document, since iframes w ith
211 // no background in the child document should show the parent's background.
212 bool isOpaque = true;
213 Element* ownerElement = document().ownerElement();
214 if (ownerElement) {
215 if (!isHTMLFrameElement(*ownerElement)) {
216 // Locate the <body> element using the DOM. This is easier than tryi ng
217 // to crawl around a render tree with potential :before/:after conte nt and
218 // anonymous blocks created by inline <body> tags etc. We can locate the <body>
219 // render object very easily via the DOM.
220 HTMLElement* body = document().body();
221 if (body) {
222 // Can't scroll a frameset document anyway.
223 isOpaque = body->hasTagName(framesetTag);
224 } else {
225 // FIXME: SVG specific behavior should be in the SVG code.
226 // SVG documents and XML documents with SVG root nodes are trans parent.
227 isOpaque = !document().hasSVGRootNode();
228 }
229 }
230 } else if (view()->frameView()) {
231 isOpaque = !view()->frameView()->isTransparent();
232 }
233
234 return isOpaque;
235 }
236
237 void RenderBoxModelObject::paintRootBackgroundColor(const PaintInfo& paintInfo, const LayoutRect& rect, const Color& bgColor)
238 {
239 GraphicsContext* context = paintInfo.context;
240 if (rect.isEmpty())
241 return;
242
243 ASSERT(isDocumentElement());
244
245 IntRect backgroundRect(pixelSnappedIntRect(rect));
246 backgroundRect.intersect(paintInfo.rect);
247
248 Color baseColor = view()->frameView()->baseBackgroundColor();
249 bool shouldClearDocumentBackground = document().settings() && document().set tings()->shouldClearDocumentBackground();
250 CompositeOperator operation = shouldClearDocumentBackground ? CompositeCopy : context->compositeOperation();
251
252 // If we have an alpha go ahead and blend with the base background color.
253 if (baseColor.alpha()) {
254 if (bgColor.alpha())
255 baseColor = baseColor.blend(bgColor);
256 context->fillRect(backgroundRect, baseColor, operation);
257 } else if (bgColor.alpha()) {
258 context->fillRect(backgroundRect, bgColor, operation);
259 } else if (shouldClearDocumentBackground) {
260 context->clearRect(backgroundRect);
261 }
262 }
263
264 LayoutSize RenderBoxModelObject::relativePositionOffset() const 195 LayoutSize RenderBoxModelObject::relativePositionOffset() const
265 { 196 {
266 LayoutSize offset = accumulateInFlowPositionOffsets(this); 197 LayoutSize offset = accumulateInFlowPositionOffsets(this);
267 198
268 RenderBlock* containingBlock = this->containingBlock(); 199 RenderBlock* containingBlock = this->containingBlock();
269 200
270 // Objects that shrink to avoid floats normally use available line width whe n computing containing block width. However 201 // Objects that shrink to avoid floats normally use available line width whe n computing containing block width. However
271 // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the 202 // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the
272 // available width of the containing block. Therefore we don't use containi ngBlockLogicalWidthForContent() here, but instead explicitly 203 // available width of the containing block. Therefore we don't use containi ngBlockLogicalWidthForContent() here, but instead explicitly
273 // call availableWidth on our containing block. 204 // call availableWidth on our containing block.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 } 304 }
374 305
375 LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const 306 LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const
376 { 307 {
377 LayoutUnit w = 0; 308 LayoutUnit w = 0;
378 if (padding.isPercent()) 309 if (padding.isPercent())
379 w = containingBlockLogicalWidthForContent(); 310 w = containingBlockLogicalWidthForContent();
380 return minimumValueForLength(padding, w); 311 return minimumValueForLength(padding, w);
381 } 312 }
382 313
383 RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& bor derRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeig ht,
384 bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
385 {
386 RoundedRect border = style()->getRoundedBorderFor(borderRect, includeLogical LeftEdge, includeLogicalRightEdge);
387 if (box && (box->nextLineBox() || box->prevLineBox())) {
388 RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0 , inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightE dge);
389 border.setRadii(segmentBorder.radii());
390 }
391
392 return border;
393 }
394
395 void RenderBoxModelObject::clipRoundedInnerRect(GraphicsContext * context, const LayoutRect& rect, const RoundedRect& clipRect)
396 {
397 if (clipRect.isRenderable())
398 context->clipRoundedRect(clipRect);
399 else {
400 // We create a rounded rect for each of the corners and clip it, while m aking sure we clip opposing corners together.
401 if (!clipRect.radii().topLeft().isEmpty() || !clipRect.radii().bottomRig ht().isEmpty()) {
402 IntRect topCorner(clipRect.rect().x(), clipRect.rect().y(), rect.max X() - clipRect.rect().x(), rect.maxY() - clipRect.rect().y());
403 RoundedRect::Radii topCornerRadii;
404 topCornerRadii.setTopLeft(clipRect.radii().topLeft());
405 context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii));
406
407 IntRect bottomCorner(rect.x(), rect.y(), clipRect.rect().maxX() - re ct.x(), clipRect.rect().maxY() - rect.y());
408 RoundedRect::Radii bottomCornerRadii;
409 bottomCornerRadii.setBottomRight(clipRect.radii().bottomRight());
410 context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii ));
411 }
412
413 if (!clipRect.radii().topRight().isEmpty() || !clipRect.radii().bottomLe ft().isEmpty()) {
414 IntRect topCorner(rect.x(), clipRect.rect().y(), clipRect.rect().max X() - rect.x(), rect.maxY() - clipRect.rect().y());
415 RoundedRect::Radii topCornerRadii;
416 topCornerRadii.setTopRight(clipRect.radii().topRight());
417 context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii));
418
419 IntRect bottomCorner(clipRect.rect().x(), rect.y(), rect.maxX() - cl ipRect.rect().x(), clipRect.rect().maxY() - rect.y());
420 RoundedRect::Radii bottomCornerRadii;
421 bottomCornerRadii.setBottomLeft(clipRect.radii().bottomLeft());
422 context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii ));
423 }
424 }
425 }
426
427 // FIXME: See crbug.com/382491. The use of getCTM in this context is incorrect b ecause the matrix returned does not 314 // FIXME: See crbug.com/382491. The use of getCTM in this context is incorrect b ecause the matrix returned does not
428 // include scales applied at raster time, such as the device zoom. 315 // include scales applied at raster time, such as the device zoom.
429 static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRec t& rect) 316 static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRec t& rect)
430 { 317 {
431 LayoutRect shrunkRect = rect; 318 LayoutRect shrunkRect = rect;
432 AffineTransform transform = context->getCTM(); 319 AffineTransform transform = context->getCTM();
433 shrunkRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale()))); 320 shrunkRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale())));
434 shrunkRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale()))); 321 shrunkRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale())));
435 return shrunkRect; 322 return shrunkRect;
436 } 323 }
437 324
438 LayoutRect RenderBoxModelObject::borderInnerRectAdjustedForBleedAvoidance(Graphi csContext* context, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoida nce) const 325 LayoutRect RenderBoxModelObject::borderInnerRectAdjustedForBleedAvoidance(Graphi csContext* context, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoida nce) const
439 { 326 {
440 // We shrink the rectangle by one pixel on each side to make it fully overla p the anti-aliased background border 327 // We shrink the rectangle by one pixel on each side to make it fully overla p the anti-aliased background border
441 return (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? shrinkRectB yOnePixel(context, rect) : rect; 328 return (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? shrinkRectB yOnePixel(context, rect) : rect;
442 } 329 }
443 330
444 RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance (GraphicsContext* context, const LayoutRect& borderRect, BackgroundBleedAvoidanc e bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, bool includeLog icalLeftEdge, bool includeLogicalRightEdge) const
445 {
446 if (bleedAvoidance == BackgroundBleedShrinkBackground) {
447 // We shrink the rectangle by one pixel on each side because the bleed i s one pixel maximum.
448 return getBackgroundRoundedRect(shrinkRectByOnePixel(context, borderRect ), box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogica lRightEdge);
449 }
450 if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
451 return style()->getRoundedInnerBorderFor(borderRect, includeLogicalLeftE dge, includeLogicalRightEdge);
452
453 return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.he ight(), includeLogicalLeftEdge, includeLogicalRightEdge);
454 }
455
456 static void applyBoxShadowForBackground(GraphicsContext* context, const RenderOb ject* renderer)
457 {
458 const ShadowList* shadowList = renderer->style()->boxShadow();
459 ASSERT(shadowList);
460 for (size_t i = shadowList->shadows().size(); i--; ) {
461 const ShadowData& boxShadow = shadowList->shadows()[i];
462 if (boxShadow.style() != Normal)
463 continue;
464 FloatSize shadowOffset(boxShadow.x(), boxShadow.y());
465 context->setShadow(shadowOffset, boxShadow.blur(), boxShadow.color(),
466 DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::Shad owIgnoresAlpha);
467 return;
468 }
469 }
470
471 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co nst Color& color, const FillLayer& bgLayer, const LayoutRect& rect,
472 BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSiz e& boxSize, CompositeOperator op, RenderObject* backgroundObject, bool skipBaseC olor)
473 {
474 GraphicsContext* context = paintInfo.context;
475 if (rect.isEmpty())
476 return;
477
478 bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true;
479 bool includeRightEdge = box ? box->includeLogicalRightEdge() : true;
480
481 bool hasRoundedBorder = style()->hasBorderRadius() && (includeLeftEdge || in cludeRightEdge);
482 bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer.attachment() = = LocalBackgroundAttachment;
483 bool isBorderFill = bgLayer.clip() == BorderFillBox;
484 bool isDocumentElementRenderer = this->isDocumentElement();
485 bool isBottomLayer = !bgLayer.next();
486
487 Color bgColor = color;
488 StyleImage* bgImage = bgLayer.image();
489 bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(*this, style ()->effectiveZoom());
490
491 bool forceBackgroundToWhite = false;
492 if (document().printing()) {
493 if (style()->printColorAdjust() == PrintColorAdjustEconomy)
494 forceBackgroundToWhite = true;
495 if (document().settings() && document().settings()->shouldPrintBackgroun ds())
496 forceBackgroundToWhite = false;
497 }
498
499 // When printing backgrounds is disabled or using economy mode,
500 // change existing background colors and images to a solid white background.
501 // If there's no bg color or image, leave it untouched to avoid affecting tr ansparency.
502 // We don't try to avoid loading the background images, because this style f lag is only set
503 // when printing, and at that point we've already loaded the background imag es anyway. (To avoid
504 // loading the background images we'd have to do this check when applying st yles rather than
505 // while rendering.)
506 if (forceBackgroundToWhite) {
507 // Note that we can't reuse this variable below because the bgColor migh t be changed
508 bool shouldPaintBackgroundColor = isBottomLayer && bgColor.alpha();
509 if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
510 bgColor = Color::white;
511 shouldPaintBackgroundImage = false;
512 }
513 }
514
515 bool colorVisible = bgColor.alpha();
516
517 // Fast path for drawing simple color backgrounds.
518 if (!isDocumentElementRenderer && !clippedWithLocalScrolling && !shouldPaint BackgroundImage && isBorderFill && isBottomLayer) {
519 if (!colorVisible)
520 return;
521
522 bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppli edToBackground(bleedAvoidance, box);
523 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAp pliedToBackground);
524 if (boxShadowShouldBeAppliedToBackground)
525 applyBoxShadowForBackground(context, this);
526
527 if (hasRoundedBorder && bleedAvoidance != BackgroundBleedClipBackground) {
528 RoundedRect border = backgroundRoundedRectAdjustedForBleedAvoidance( context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge);
529 if (border.isRenderable())
530 context->fillRoundedRect(border, bgColor);
531 else {
532 context->save();
533 clipRoundedInnerRect(context, rect, border);
534 context->fillRect(border.rect(), bgColor);
535 context->restore();
536 }
537 } else {
538 context->fillRect(pixelSnappedIntRect(rect), bgColor);
539 }
540
541 return;
542 }
543
544 // BorderFillBox radius clipping is taken care of by BackgroundBleedClipBack ground
545 bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidan ce == BackgroundBleedClipBackground);
546 GraphicsContextStateSaver clipToBorderStateSaver(*context, clipToBorderRadiu s);
547 if (clipToBorderRadius) {
548 RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBlee dAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, include RightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height (), includeLeftEdge, includeRightEdge);
549
550 // Clip to the padding or content boxes as necessary.
551 if (bgLayer.clip() == ContentFillBox) {
552 border = style()->getRoundedInnerBorderFor(border.rect(),
553 paddingTop() + borderTop(), paddingBottom() + borderBottom(), pa ddingLeft() + borderLeft(), paddingRight() + borderRight(), includeLeftEdge, inc ludeRightEdge);
554 } else if (bgLayer.clip() == PaddingFillBox)
555 border = style()->getRoundedInnerBorderFor(border.rect(), includeLef tEdge, includeRightEdge);
556
557 clipRoundedInnerRect(context, rect, border);
558 }
559
560 int bLeft = includeLeftEdge ? borderLeft() : 0;
561 int bRight = includeRightEdge ? borderRight() : 0;
562 LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : LayoutUnit();
563 LayoutUnit pRight = includeRightEdge ? paddingRight() : LayoutUnit();
564
565 GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithL ocalScrolling);
566 LayoutRect scrolledPaintRect = rect;
567 if (clippedWithLocalScrolling) {
568 // Clip to the overflow area.
569 RenderBox* thisBox = toRenderBox(this);
570 context->clip(thisBox->overflowClipRect(rect.location()));
571
572 // Adjust the paint rect to reflect a scrolled content box with borders at the ends.
573 IntSize offset = thisBox->scrolledContentOffset();
574 scrolledPaintRect.move(-offset);
575 scrolledPaintRect.setWidth(bLeft + thisBox->scrollWidth() + bRight);
576 scrolledPaintRect.setHeight(borderTop() + thisBox->scrollHeight() + bord erBottom());
577 }
578
579 GraphicsContextStateSaver backgroundClipStateSaver(*context, false);
580 IntRect maskRect;
581
582 switch (bgLayer.clip()) {
583 case PaddingFillBox:
584 case ContentFillBox: {
585 if (clipToBorderRadius)
586 break;
587
588 // Clip to the padding or content boxes as necessary.
589 bool includePadding = bgLayer.clip() == ContentFillBox;
590 LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includ ePadding ? pLeft : LayoutUnit()),
591 scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : LayoutUnit()),
592 scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : LayoutUnit()),
593 scrolledPaintRect.height() - borderTop() - borderBottom() - (include Padding ? paddingTop() + paddingBottom() : LayoutUnit()));
594 backgroundClipStateSaver.save();
595 context->clip(clipRect);
596
597 break;
598 }
599 case TextFillBox: {
600 // First figure out how big the mask has to be. It should be no bigger than what we need
601 // to actually render, so we should intersect the dirty rect with the bo rder box of the background.
602 maskRect = pixelSnappedIntRect(rect);
603 maskRect.intersect(paintInfo.rect);
604
605 // We draw the background into a separate layer, to be later masked with yet another layer
606 // holding the text content.
607 backgroundClipStateSaver.save();
608 context->clip(maskRect);
609 context->beginTransparencyLayer(1);
610
611 break;
612 }
613 case BorderFillBox:
614 break;
615 default:
616 ASSERT_NOT_REACHED();
617 break;
618 }
619
620 // Paint the color first underneath all images, culled if background image o ccludes it.
621 // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culli ng test
622 // by verifying whether the background image covers the entire layout rect.
623 if (isBottomLayer) {
624 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
625 bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppli edToBackground(bleedAvoidance, box);
626 bool isOpaqueRoot = (isDocumentElementRenderer && !bgColor.hasAlpha()) | | isDocumentElementWithOpaqueBackground();
627 if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer.hasOpaqueImage(this) || !bgLayer.hasRepeatXY() || (isOpaqueRoot && ! toRenderBox(this)->height())) {
628 if (!boxShadowShouldBeAppliedToBackground)
629 backgroundRect.intersect(paintInfo.rect);
630
631 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould BeAppliedToBackground);
632 if (boxShadowShouldBeAppliedToBackground)
633 applyBoxShadowForBackground(context, this);
634
635 if (isOpaqueRoot && !skipBaseColor) {
636 paintRootBackgroundColor(paintInfo, rect, bgColor);
637 } else if (bgColor.alpha()) {
638 context->fillRect(backgroundRect, bgColor, context->compositeOpe ration());
639 }
640 }
641 }
642
643 // no progressive loading of the background image
644 if (shouldPaintBackgroundImage) {
645 BackgroundImageGeometry geometry;
646 calculateBackgroundImageGeometry(paintInfo.paintContainer(), bgLayer, sc rolledPaintRect, geometry, backgroundObject);
647 geometry.clip(paintInfo.rect);
648 if (!geometry.destRect().isEmpty()) {
649 CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer. composite() : op;
650 RenderObject* clientForBackgroundImage = backgroundObject ? backgrou ndObject : this;
651 RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geome try.tileSize());
652 InterpolationQuality interpolationQuality = chooseInterpolationQuali ty(context, image.get(), &bgLayer, geometry.tileSize());
653 if (bgLayer.maskSourceType() == MaskLuminance)
654 context->setColorFilter(ColorFilterLuminanceToAlpha);
655 InterpolationQuality previousInterpolationQuality = context->imageIn terpolationQuality();
656 context->setImageInterpolationQuality(interpolationQuality);
657 context->drawTiledImage(image.get(), geometry.destRect(), geometry.r elativePhase(), geometry.tileSize(),
658 compositeOp, bgLayer.blendMode(), geometry.spaceSize());
659 context->setImageInterpolationQuality(previousInterpolationQuality);
660 }
661 }
662
663 if (bgLayer.clip() == TextFillBox) {
664 // Create the text mask layer.
665 context->setCompositeOperation(CompositeDestinationIn);
666 context->beginTransparencyLayer(1);
667
668 // FIXME: Workaround for https://code.google.com/p/skia/issues/detail?id =1291.
669 context->clearRect(maskRect);
670
671 // Now draw the text into the mask. We do this by painting using a speci al paint phase that signals to
672 // InlineTextBoxes that they should just add their contents to the clip.
673 PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForce BlackText, 0);
674 context->setCompositeOperation(CompositeSourceOver);
675 if (box) {
676 RootInlineBox& root = box->root();
677 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrol ledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom());
678 } else {
679 LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset () : LayoutSize();
680 paint(info, scrolledPaintRect.location() - localOffset);
681 }
682
683 context->endLayer();
684 context->endLayer();
685 }
686 }
687
688 static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRat io) 331 static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRat io)
689 { 332 {
690 return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height()); 333 return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height());
691 } 334 }
692 335
693 static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRat io) 336 static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRat io)
694 { 337 {
695 return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width()); 338 return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width());
696 } 339 }
697 340
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that 411 // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that
769 // establishes the coordinate system for the 'background-position' property. 412 // establishes the coordinate system for the 'background-position' property.
770 if (!intrinsicRatio.isEmpty()) 413 if (!intrinsicRatio.isEmpty())
771 return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio) ; 414 return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio) ;
772 415
773 // If the image has no intrinsic ratio either, then the dimensions must be a ssumed to be the rectangle that 416 // If the image has no intrinsic ratio either, then the dimensions must be a ssumed to be the rectangle that
774 // establishes the coordinate system for the 'background-position' property. 417 // establishes the coordinate system for the 'background-position' property.
775 return positioningAreaSize; 418 return positioningAreaSize;
776 } 419 }
777 420
778 static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize)
779 {
780 tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tile Size.width().ceil() : tileSize.width().floor());
781 tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? t ileSize.height().ceil() : tileSize.height().floor());
782 }
783
784 IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer& fillLayer, const IntSize& positioningAreaSize) const
785 {
786 StyleImage* image = fillLayer.image();
787 EFillSizeType type = fillLayer.size().type;
788
789 IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positi oningAreaSize, ScaleByEffectiveZoom);
790 imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScal eFactor());
791 switch (type) {
792 case SizeLength: {
793 LayoutSize tileSize = positioningAreaSize;
794
795 Length layerWidth = fillLayer.size().size.width();
796 Length layerHeight = fillLayer.size().size.height();
797
798 if (layerWidth.isFixed())
799 tileSize.setWidth(layerWidth.value());
800 else if (layerWidth.isPercent())
801 tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize .width()));
802
803 if (layerHeight.isFixed())
804 tileSize.setHeight(layerHeight.value());
805 else if (layerHeight.isPercent())
806 tileSize.setHeight(valueForLength(layerHeight, positioningAreaSi ze.height()));
807
808 applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize);
809
810 // If one of the values is auto we have to use the appropriate
811 // scale to maintain our aspect ratio.
812 if (layerWidth.isAuto() && !layerHeight.isAuto()) {
813 if (imageIntrinsicSize.height())
814 tileSize.setWidth(imageIntrinsicSize.width() * tileSize.heig ht() / imageIntrinsicSize.height());
815 } else if (!layerWidth.isAuto() && layerHeight.isAuto()) {
816 if (imageIntrinsicSize.width())
817 tileSize.setHeight(imageIntrinsicSize.height() * tileSize.wi dth() / imageIntrinsicSize.width());
818 } else if (layerWidth.isAuto() && layerHeight.isAuto()) {
819 // If both width and height are auto, use the image's intrinsic size.
820 tileSize = imageIntrinsicSize;
821 }
822
823 tileSize.clampNegativeToZero();
824 return flooredIntSize(tileSize);
825 }
826 case SizeNone: {
827 // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any.
828 if (!imageIntrinsicSize.isEmpty())
829 return imageIntrinsicSize;
830
831 // If the image has neither an intrinsic width nor an intrinsic heig ht, its size is determined as for ‘contain’.
832 type = Contain;
833 }
834 case Contain:
835 case Cover: {
836 float horizontalScaleFactor = imageIntrinsicSize.width()
837 ? static_cast<float>(positioningAreaSize.width()) / imageIntrins icSize.width() : 1;
838 float verticalScaleFactor = imageIntrinsicSize.height()
839 ? static_cast<float>(positioningAreaSize.height()) / imageIntrin sicSize.height() : 1;
840 float scaleFactor = type == Contain ? std::min(horizontalScaleFactor , verticalScaleFactor) : std::max(horizontalScaleFactor, verticalScaleFactor);
841 return IntSize(std::max(1l, lround(imageIntrinsicSize.width() * scal eFactor)), std::max(1l, lround(imageIntrinsicSize.height() * scaleFactor)));
842 }
843 }
844
845 ASSERT_NOT_REACHED();
846 return IntSize();
847 }
848
849 void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX(int xOffset)
850 {
851 m_destRect.move(std::max(xOffset, 0), 0);
852 m_phase.setX(-std::min(xOffset, 0));
853 m_destRect.setWidth(m_tileSize.width() + std::min(xOffset, 0));
854 }
855 void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY(int yOffset)
856 {
857 m_destRect.move(0, std::max(yOffset, 0));
858 m_phase.setY(-std::min(yOffset, 0));
859 m_destRect.setHeight(m_tileSize.height() + std::min(yOffset, 0));
860 }
861
862 void RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment(const Int Point& attachmentPoint)
863 {
864 IntPoint alignedPoint = attachmentPoint;
865 m_phase.move(std::max(alignedPoint.x() - m_destRect.x(), 0), std::max(aligne dPoint.y() - m_destRect.y(), 0));
866 }
867
868 void RenderBoxModelObject::BackgroundImageGeometry::clip(const IntRect& clipRect )
869 {
870 m_destRect.intersect(clipRect);
871 }
872
873 IntPoint RenderBoxModelObject::BackgroundImageGeometry::relativePhase() const
874 {
875 IntPoint phase = m_phase;
876 phase += m_destRect.location() - m_destOrigin;
877 return phase;
878 }
879
880 bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const
881 {
882 if (!isDocumentElement())
883 return false;
884
885 if (view()->frameView() && view()->frameView()->paintBehavior() & PaintBehav iorFlattenCompositingLayers)
886 return false;
887
888 RenderLayer* rootLayer = view()->layer();
889 if (!rootLayer || rootLayer->compositingState() == NotComposited)
890 return false;
891
892 return rootLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBa ckground();
893 }
894
895 static inline int getSpace(int areaSize, int tileSize)
896 {
897 int numberOfTiles = areaSize / tileSize;
898 int space = -1;
899
900 if (numberOfTiles > 1)
901 space = lroundf((float)(areaSize - numberOfTiles * tileSize) / (numberOf Tiles - 1));
902
903 return space;
904 }
905
906 void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerMod elObject* paintContainer, const FillLayer& fillLayer, const LayoutRect& paintRec t,
907 BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const
908 {
909 LayoutUnit left = 0;
910 LayoutUnit top = 0;
911 IntSize positioningAreaSize;
912 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect);
913
914 // Determine the background positioning area and set destRect to the backgro und painting area.
915 // destRect will be adjusted later if the background is non-repeating.
916 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms.
917 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment;
918
919 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) {
920 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS
921 // property "background-attachment: fixed" because it may result in rend ering
922 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of
923 // a page that has fixed background images.
924 fixedAttachment = false;
925 }
926
927 if (!fixedAttachment) {
928 geometry.setDestRect(snappedPaintRect);
929
930 LayoutUnit right = 0;
931 LayoutUnit bottom = 0;
932 // Scroll and Local.
933 if (fillLayer.origin() != BorderFillBox) {
934 left = borderLeft();
935 right = borderRight();
936 top = borderTop();
937 bottom = borderBottom();
938 if (fillLayer.origin() == ContentFillBox) {
939 left += paddingLeft();
940 right += paddingRight();
941 top += paddingTop();
942 bottom += paddingBottom();
943 }
944 }
945
946 // The background of the box generated by the root element covers the en tire canvas including
947 // its margins. Since those were added in already, we have to factor the m out when computing
948 // the background positioning area.
949 if (isDocumentElement()) {
950 positioningAreaSize = pixelSnappedIntSize(toRenderBox(this)->size() - LayoutSize(left + right, top + bottom), toRenderBox(this)->location());
951 left += marginLeft();
952 top += marginTop();
953 } else
954 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location());
955 } else {
956 geometry.setHasNonLocalGeometry();
957
958 IntRect viewportRect = pixelSnappedIntRect(viewRect());
959 if (fixedBackgroundPaintsInLocalCoordinates())
960 viewportRect.setLocation(IntPoint());
961 else if (FrameView* frameView = view()->frameView())
962 viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPos ition()));
963
964 if (paintContainer) {
965 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint()));
966 viewportRect.moveBy(-absoluteContainerOffset);
967 }
968
969 geometry.setDestRect(pixelSnappedIntRect(viewportRect));
970 positioningAreaSize = geometry.destRect().size();
971 }
972
973 const RenderObject* clientForBackgroundImage = backgroundObject ? background Object : this;
974 IntSize fillTileSize = calculateFillTileSize(fillLayer, positioningAreaSize) ;
975 fillLayer.image()->setContainerSizeForRenderer(clientForBackgroundImage, fil lTileSize, style()->effectiveZoom());
976 geometry.setTileSize(fillTileSize);
977
978 EFillRepeat backgroundRepeatX = fillLayer.repeatX();
979 EFillRepeat backgroundRepeatY = fillLayer.repeatY();
980 int availableWidth = positioningAreaSize.width() - geometry.tileSize().width ();
981 int availableHeight = positioningAreaSize.height() - geometry.tileSize().hei ght();
982
983 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth);
984 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) {
985 long nrTiles = std::max(1l, lroundf((float)positioningAreaSize.width() / fillTileSize.width()));
986
987 if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != Roun dFill) {
988 fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.w idth() / (nrTiles * fillTileSize.width()));
989 }
990
991 fillTileSize.setWidth(positioningAreaSize.width() / nrTiles);
992 geometry.setTileSize(fillTileSize);
993 geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().wid th() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
994 geometry.setSpaceSize(IntSize());
995 }
996
997 LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosit ion(), availableHeight);
998 if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > 0 && fi llTileSize.height() > 0) {
999 long nrTiles = std::max(1l, lroundf((float)positioningAreaSize.height() / fillTileSize.height()));
1000
1001 if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != Round Fill) {
1002 fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.hei ght() / (nrTiles * fillTileSize.height()));
1003 }
1004
1005 fillTileSize.setHeight(positioningAreaSize.height() / nrTiles);
1006 geometry.setTileSize(fillTileSize);
1007 geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().he ight() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0) ;
1008 geometry.setSpaceSize(IntSize());
1009 }
1010
1011 if (backgroundRepeatX == RepeatFill) {
1012 geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().wid th() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
1013 geometry.setSpaceSize(IntSize());
1014 } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > 0) {
1015 int space = getSpace(positioningAreaSize.width(), geometry.tileSize().wi dth());
1016 int actualWidth = geometry.tileSize().width() + space;
1017
1018 if (space >= 0) {
1019 computedXPosition = roundedMinimumValueForLength(Length(), available Width);
1020 geometry.setSpaceSize(IntSize(space, 0));
1021 geometry.setPhaseX(actualWidth ? actualWidth - roundToInt(computedXP osition + left) % actualWidth : 0);
1022 } else {
1023 backgroundRepeatX = NoRepeatFill;
1024 }
1025 }
1026 if (backgroundRepeatX == NoRepeatFill) {
1027 int xOffset = fillLayer.backgroundXOrigin() == RightEdge ? availableWidt h - computedXPosition : computedXPosition;
1028 geometry.setNoRepeatX(left + xOffset);
1029 geometry.setSpaceSize(IntSize(0, geometry.spaceSize().height()));
1030 }
1031
1032 if (backgroundRepeatY == RepeatFill) {
1033 geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().he ight() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0) ;
1034 geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), 0));
1035 } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > 0) {
1036 int space = getSpace(positioningAreaSize.height(), geometry.tileSize().h eight());
1037 int actualHeight = geometry.tileSize().height() + space;
1038
1039 if (space >= 0) {
1040 computedYPosition = roundedMinimumValueForLength(Length(), available Height);
1041 geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), space));
1042 geometry.setPhaseY(actualHeight ? actualHeight - roundToInt(computed YPosition + top) % actualHeight : 0);
1043 } else {
1044 backgroundRepeatY = NoRepeatFill;
1045 }
1046 }
1047 if (backgroundRepeatY == NoRepeatFill) {
1048 int yOffset = fillLayer.backgroundYOrigin() == BottomEdge ? availableHei ght - computedYPosition : computedYPosition;
1049 geometry.setNoRepeatY(top + yOffset);
1050 geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), 0));
1051 }
1052
1053 if (fixedAttachment)
1054 geometry.useFixedAttachment(snappedPaintRect.location());
1055
1056 geometry.clip(snappedPaintRect);
1057 geometry.setDestOrigin(geometry.destRect().location());
1058 }
1059
1060 static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, L ayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent) 421 static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, L ayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent)
1061 { 422 {
1062 if (borderSlice.isNumber()) 423 if (borderSlice.isNumber())
1063 return borderSlice.number() * borderSide; 424 return borderSlice.number() * borderSide;
1064 if (borderSlice.length().isAuto()) 425 if (borderSlice.length().isAuto())
1065 return imageSide; 426 return imageSide;
1066 return valueForLength(borderSlice.length(), boxExtent); 427 return valueForLength(borderSlice.length(), boxExtent);
1067 } 428 }
1068 429
1069 bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style, 430 bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style,
(...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); 1965 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
2605 for (RenderObject* child = startChild; child && child != endChild; ) { 1966 for (RenderObject* child = startChild; child && child != endChild; ) {
2606 // Save our next sibling as moveChildTo will clear it. 1967 // Save our next sibling as moveChildTo will clear it.
2607 RenderObject* nextSibling = child->nextSibling(); 1968 RenderObject* nextSibling = child->nextSibling();
2608 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); 1969 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
2609 child = nextSibling; 1970 child = nextSibling;
2610 } 1971 }
2611 } 1972 }
2612 1973
2613 } // namespace blink 1974 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698