15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (C) 1999 Antti Koivisto (koivisto@kde.org) 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved. 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderBoxModelObject.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h" 3009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/frame/Settings.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLFrameOwnerElement.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/scrolling/ScrollingConstraints.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/ImageQualityController.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderBlock.h" 3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/rendering/RenderFlowThread.h" 36521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "core/rendering/RenderGeometryMap.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderInline.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderLayer.h" 3993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "core/rendering/RenderRegion.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderView.h" 41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/rendering/compositing/CompositedLayerMapping.h" 42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/rendering/compositing/RenderLayerCompositor.h" 43f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "core/rendering/style/ShadowList.h" 44bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/geometry/TransformState.h" 45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "platform/graphics/DrawLooperBuilder.h" 46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h" 47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/Path.h" 4802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#include "wtf/CurrentTime.h" 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames; 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The HashMap for storing continuation pointers. 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// An inline can be split with blocks occuring in between the inline content. 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// When this occurs we need a pointer to the next object. We can basically be 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// split into a sequence of inlines and blocks. The continuation will either be 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// an anonymous block (that houses other blocks) or it will be an inline flow. 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// its continuation but the <b> will just have an inline as its continuation. 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef HashMap<const RenderBoxModelObject*, RenderBoxModelObject*> ContinuationMap; 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static ContinuationMap* continuationMap = 0; 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This HashMap is similar to the continuation map, but connects first-letter 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// renderers to their remaining text fragments. 6851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)typedef HashMap<const RenderBoxModelObject*, RenderTextFragment*> FirstLetterRemainingTextMap; 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static FirstLetterRemainingTextMap* firstLetterRemainingTextMap = 0; 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::setSelectionState(SelectionState state) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (state == SelectionInside && selectionState() != SelectionNone) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((state == SelectionStart && selectionState() == SelectionEnd) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (state == SelectionEnd && selectionState() == SelectionStart)) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject::setSelectionState(SelectionBoth); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject::setSelectionState(state); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We should consider whether it is OK propagating to ancestor RenderInlines. 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is a workaround for http://webkit.org/b/32123 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The containing block can be null in case of an orphaned tree. 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBlock* containingBlock = this->containingBlock(); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (containingBlock && !containingBlock->isRenderView()) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) containingBlock->setSelectionState(state); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::contentChanged(ContentChangeType changeType) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!hasLayer()) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) layer()->contentChanged(changeType); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::hasAcceleratedCompositing() const 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return view()->compositor()->hasAcceleratedCompositing(); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)InterpolationQuality RenderBoxModelObject::chooseInterpolationQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 10543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) return ImageQualityController::imageQualityController()->chooseInterpolationQuality(context, this, image, layer, size); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : RenderLayerModelObject(node) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderBoxModelObject::~RenderBoxModelObject() 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 11553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ImageQualityController::remove(this); 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::willBeDestroyed() 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A continuation of this RenderObject should be destroyed at subclasses. 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!continuation()); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If this is a first-letter object with a remaining text fragment then the 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // entry needs to be cleared from the map. 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (firstLetterRemainingText()) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setFirstLetterRemainingText(0); 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderLayerModelObject::willBeDestroyed(); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochbool RenderBoxModelObject::calculateHasBoxDecorations() const 132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{ 133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch RenderStyle* styleToUse = style(); 134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ASSERT(styleToUse); 135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow(); 136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::updateFromStyle() 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderLayerModelObject::updateFromStyle(); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderStyle* styleToUse = style(); 143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch setHasBoxDecorations(calculateHasBoxDecorations()); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setInline(styleToUse->isDisplayInlineType()); 145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setPositionState(styleToUse->position()); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setHorizontalWritingMode(styleToUse->isHorizontalWritingMode()); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!child->isAnonymousBlock() || !child->isInFlowPositioned()) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutSize(); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutSize offset; 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject* p = toRenderBlock(child)->inlineElementContinuation(); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (p && p->isRenderInline()) { 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (p->isInFlowPositioned()) { 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderInline* renderInline = toRenderInline(p); 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) offset += renderInline->offsetForInFlowPosition(); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) p = p->parent(); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return offset; 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const 166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Length logicalHeightLength = style()->logicalHeight(); 168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (logicalHeightLength.isAuto()) 169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // For percentage heights: The percentage is calculated with respect to the height of the generated box's 172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // containing block. If the height of the containing block is not specified explicitly (i.e., it depends 173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // on content height), and this element is not absolutely positioned, the value computes to 'auto'. 1748abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (!logicalHeightLength.isPercent() || isOutOfFlowPositioned() || document().inQuirksMode()) 175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 17753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Anonymous block boxes are ignored when resolving percentage values that would refer to it: 17853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // the closest non-anonymous ancestor box is used instead. 17902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch RenderBlock* cb = containingBlock(); 18053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) while (cb->isAnonymous()) 181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) cb = cb->containingBlock(); 182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // Matching RenderBox::percentageLogicalHeightIsResolvableFromBlock() by 18453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // ignoring table cell's attribute value, where it says that table cells violate 18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // what the CSS spec says to do with heights. Basically we 18653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // don't care if the cell specified a height or not. 18753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (cb->isTableCell()) 18853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 18902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 19010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // Match RenderBox::availableLogicalHeightUsing by special casing 19110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // the render view. The available height is taken from the frame. 19210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (cb->isRenderView()) 19310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 19410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!cb->style()->logicalHeight().isAuto() || (!cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto())) 196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutSize RenderBoxModelObject::relativePositionOffset() const 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutSize offset = accumulateInFlowPositionOffsets(this); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBlock* containingBlock = this->containingBlock(); 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Objects that shrink to avoid floats normally use available line width when computing containing block width. However 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // available width of the containing block. Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // call availableWidth on our containing block. 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->left().isAuto()) { 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection()) 21309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth())); 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 21509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) offset.expand(valueForLength(style()->left(), containingBlock->availableWidth()), 0); 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (!style()->right().isAuto()) { 21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth()), 0); 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the containing block of a relatively positioned element does not 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // specify a height, a percentage top or bottom offset should be resolved as 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // auto. An exception to this is if the containing block has the WinIE quirk 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // where <html> and <body> assume the size of the viewport. In this case, 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // calculate the percent offset based on this height. 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // See <https://bugs.webkit.org/show_bug.cgi?id=26396>. 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->top().isAuto() 227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || !style()->top().isPercent() 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || containingBlock->stretchesToViewport())) 23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight())); 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (!style()->bottom().isAuto() 233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || !style()->bottom().isPercent() 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || containingBlock->stretchesToViewport())) 23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight())); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return offset; 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const LayoutPoint& startPoint) const 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the element is the HTML body element or doesn't have a parent 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // return 0 and stop this algorithm. 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isBody() || !parent()) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutPoint(); 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutPoint referencePoint = startPoint; 249f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu referencePoint.move(parent()->columnOffset(referencePoint)); 25002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the offsetParent of the element is null, or is the HTML body element, 25202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // return the distance between the canvas origin and the left border edge 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // of the element and stop this algorithm. 25453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) Element* element = offsetParent(); 25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!element) 25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return referencePoint; 25753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject()) { 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (offsetParent->isBox() && !offsetParent->isBody()) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRenderBox(offsetParent)->borderTop()); 26193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isRelPositioned()) 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) referencePoint.move(relativePositionOffset()); 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (isStickyPositioned()) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) referencePoint.move(stickyPositionOffset()); 26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 26793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) RenderObject* current; 26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (current = parent(); current != offsetParent && current->parent(); current = current->parent()) { 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: What are we supposed to do inside SVG content? 27093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!isOutOfFlowPositioned()) { 27193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (current->isBox() && !current->isTableRow()) 27293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) referencePoint.moveBy(toRenderBox(current)->topLeftLocation()); 273f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu referencePoint.move(current->parent()->columnOffset(referencePoint)); 27493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned()) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation()); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return referencePoint; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewportConstraints& constraints, const FloatRect& constrainingRect) const 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBlock* containingBlock = this->containingBlock(); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect containerContentRect = containingBlock->contentBoxRect(); 290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Sticky positioned element ignore any override logical width on the containing block (as they don't call 293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // containingBlockLogicalWidthForContent). It's unclear whether this is totally fine. 29409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) LayoutBoxExtent minMargin(minimumValueForLength(style()->marginTop(), maxWidth), 29509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) minimumValueForLength(style()->marginRight(), maxWidth), 29609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) minimumValueForLength(style()->marginBottom(), maxWidth), 29709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) minimumValueForLength(style()->marginLeft(), maxWidth)); 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Compute the container-relative area within which the sticky element is allowed to move. 300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) containerContentRect.contract(minMargin); 301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Map to the view to avoid including page scale factor. 302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) constraints.setAbsoluteContainingBlockRect(containingBlock->localToContainerQuad(FloatRect(containerContentRect), view()).boundingBox()); 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect stickyBoxRect = frameRectForStickyPositioning(); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect flippedStickyBoxRect = stickyBoxRect; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) containingBlock->flipForWritingMode(flippedStickyBoxRect); 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutPoint stickyLocation = flippedStickyBoxRect.location(); 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms. 310926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Map to the view to avoid including page scale factor. 311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) FloatRect absContainerFrame = containingBlock->localToContainerQuad(FloatRect(FloatPoint(), containingBlock->size()), view()).boundingBox(); 312926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 31309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (containingBlock->hasOverflowClip()) { 31409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) IntSize scrollOffset = containingBlock->layer()->scrollableArea()->adjustedScrollOffset(); 31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) stickyLocation -= scrollOffset; 31609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 31709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can't call localToAbsolute on |this| because that will recur. FIXME: For now, assume that |this| is not transformed. 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocation, flippedStickyBoxRect.size()); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect); 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 322d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) float horizontalOffsets = constraints.rightOffset() + constraints.leftOffset(); 323d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) bool skipRight = false; 324d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) bool skipLeft = false; 325d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!style()->left().isAuto() && !style()->right().isAuto()) { 326d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (horizontalOffsets > containerContentRect.width().toFloat() 327d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) || horizontalOffsets + containerContentRect.width().toFloat() > constrainingRect.width()) { 328d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) skipRight = style()->isLeftToRightDirection(); 329d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) skipLeft = !skipRight; 330d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 331d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 332d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 333d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!style()->left().isAuto() && !skipLeft) { 334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) constraints.setLeftOffset(floatValueForLength(style()->left(), constrainingRect.width())); 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 338d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!style()->right().isAuto() && !skipRight) { 339d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) constraints.setRightOffset(floatValueForLength(style()->right(), constrainingRect.width())); 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight); 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 343d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) bool skipBottom = false; 344d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // FIXME(ostap): Exclude top or bottom edge offset depending on the writing mode when related 345d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style/2014May/0286.html 346d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) float verticalOffsets = constraints.topOffset() + constraints.bottomOffset(); 347d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!style()->top().isAuto() && !style()->bottom().isAuto()) { 348d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (verticalOffsets > containerContentRect.height().toFloat() 349d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) || verticalOffsets + containerContentRect.height().toFloat() > constrainingRect.height()) { 350d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) skipBottom = true; 351d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 352d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 353d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->top().isAuto()) { 355d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) constraints.setTopOffset(floatValueForLength(style()->top(), constrainingRect.height())); 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop); 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 359d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!style()->bottom().isAuto() && !skipBottom) { 360d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) constraints.setBottomOffset(floatValueForLength(style()->bottom(), constrainingRect.height())); 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutSize RenderBoxModelObject::stickyPositionOffset() const 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 36709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect constrainingRect; 36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 36909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(hasLayer()); 37009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RenderLayer* enclosingClippingLayer = layer()->enclosingOverflowClipLayer(ExcludeSelf); 37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (enclosingClippingLayer) { 37209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RenderBox* enclosingClippingBox = toRenderBox(enclosingClippingLayer->renderer()); 37309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) LayoutRect clipRect = enclosingClippingBox->overflowClipRect(LayoutPoint()); 374d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) clipRect.move(enclosingClippingBox->paddingLeft(), enclosingClippingBox->paddingTop()); 375d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) clipRect.contract(LayoutSize(enclosingClippingBox->paddingLeft() + enclosingClippingBox->paddingRight(), 376d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom())); 37709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) constrainingRect = enclosingClippingBox->localToContainerQuad(FloatRect(clipRect), view()).boundingBox(); 37809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else { 37909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) LayoutRect viewportRect = view()->frameView()->viewportConstrainedVisibleContentRect(); 38009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) constrainingRect = viewportRect; 38109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 38202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StickyPositionViewportConstraints constraints; 38409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) computeStickyPositionConstraints(constraints, constrainingRect); 38502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The sticky offset is physical, so we can just return the delta computed in absolute coords (though it may be wrong with transforms). 38709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return LayoutSize(constraints.computeStickyOffset(constrainingRect)); 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isRelPositioned()) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return relativePositionOffset(); 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isStickyPositioned()) 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return stickyPositionOffset(); 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutSize(); 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutUnit RenderBoxModelObject::offsetLeft() const 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that RenderInline and RenderBox override this to pass a different 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // startPoint to adjustedPositionRelativeToOffsetParent. 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutUnit RenderBoxModelObject::offsetTop() const 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that RenderInline and RenderBox override this to pass a different 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // startPoint to adjustedPositionRelativeToOffsetParent. 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adjustedPositionRelativeToOffsetParent(LayoutPoint()).y(); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int RenderBoxModelObject::pixelSnappedOffsetWidth() const 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return snapSizeToPixel(offsetWidth(), offsetLeft()); 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int RenderBoxModelObject::pixelSnappedOffsetHeight() const 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return snapSizeToPixel(offsetHeight(), offsetTop()); 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit w = 0; 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (padding.isPercent()) 429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) w = containingBlockLogicalWidthForContent(); 43009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return minimumValueForLength(padding, w); 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight, 434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 43609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RoundedRect border = style()->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge); 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (box && (box->nextLineBox() || box->prevLineBox())) { 43809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge); 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) border.setRadii(segmentBorder.radii()); 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return border; 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::clipRoundedInnerRect(GraphicsContext * context, const LayoutRect& rect, const RoundedRect& clipRect) 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.isRenderable()) 448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->clipRoundedRect(clipRect); 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We create a rounded rect for each of the corners and clip it, while making sure we clip opposing corners together. 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!clipRect.radii().topLeft().isEmpty() || !clipRect.radii().bottomRight().isEmpty()) { 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect topCorner(clipRect.rect().x(), clipRect.rect().y(), rect.maxX() - clipRect.rect().x(), rect.maxY() - clipRect.rect().y()); 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii topCornerRadii; 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) topCornerRadii.setTopLeft(clipRect.radii().topLeft()); 455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii)); 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect bottomCorner(rect.x(), rect.y(), clipRect.rect().maxX() - rect.x(), clipRect.rect().maxY() - rect.y()); 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii bottomCornerRadii; 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomCornerRadii.setBottomRight(clipRect.radii().bottomRight()); 460926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii)); 46102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch } 4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!clipRect.radii().topRight().isEmpty() || !clipRect.radii().bottomLeft().isEmpty()) { 4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect topCorner(rect.x(), clipRect.rect().y(), clipRect.rect().maxX() - rect.x(), rect.maxY() - clipRect.rect().y()); 4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii topCornerRadii; 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) topCornerRadii.setTopRight(clipRect.radii().topRight()); 467926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii)); 4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect bottomCorner(clipRect.rect().x(), rect.y(), rect.maxX() - clipRect.rect().x(), clipRect.rect().maxY() - rect.y()); 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii bottomCornerRadii; 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomCornerRadii.setBottomLeft(clipRect.radii().bottomLeft()); 472926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii)); 4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// FIXME: See crbug.com/382491. The use of getCTM in this context is incorrect because the matrix returned does not 4785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// include scales applied at raster time, such as the device zoom. 479926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRect& rect) 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LayoutRect shrunkRect = rect; 4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AffineTransform transform = context->getCTM(); 483926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) shrunkRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale()))); 484926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) shrunkRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale()))); 485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return shrunkRect; 486926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)LayoutRect RenderBoxModelObject::borderInnerRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoidance) const 489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // We shrink the rectangle by one pixel on each side to make it fully overlap the anti-aliased background border 491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? shrinkRectByOnePixel(context, rect) : rect; 492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (bleedAvoidance == BackgroundBleedShrinkBackground) { 497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // We shrink the rectangle by one pixel on each side because the bleed is one pixel maximum. 498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return getBackgroundRoundedRect(shrinkRectByOnePixel(context, borderRect), box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge); 499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (bleedAvoidance == BackgroundBleedBackgroundOverBorder) 501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return style()->getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge); 502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge); 5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochstatic void applyBoxShadowForBackground(GraphicsContext* context, const RenderObject* renderer) 5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 508f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowList* shadowList = renderer->style()->boxShadow(); 509f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) ASSERT(shadowList); 510f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (size_t i = shadowList->shadows().size(); i--; ) { 511f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowData& boxShadow = shadowList->shadows()[i]; 512f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (boxShadow.style() != Normal) 513f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) continue; 514f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FloatSize shadowOffset(boxShadow.x(), boxShadow.y()); 51509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->setShadow(shadowOffset, boxShadow.blur(), boxShadow.color(), 516d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha); 517f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) return; 518f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect, 5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderObject* backgroundObject) 5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContext* context = paintInfo.context; 5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (context->paintingDisabled() || rect.isEmpty()) 5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true; 5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool includeRightEdge = box ? box->includeLogicalRightEdge() : true; 5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasRoundedBorder = style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge); 5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment; 5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isBorderFill = bgLayer->clip() == BorderFillBox; 5346f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch bool isRoot = this->isDocumentElement(); 5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Color bgColor = color; 5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StyleImage* bgImage = bgLayer->image(); 53810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(*this, style()->effectiveZoom()); 53902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool forceBackgroundToWhite = false; 5418abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (document().printing()) { 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style()->printColorAdjust() == PrintColorAdjustEconomy) 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) forceBackgroundToWhite = true; 5448abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (document().settings() && document().settings()->shouldPrintBackgrounds()) 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) forceBackgroundToWhite = false; 5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // When printing backgrounds is disabled or using economy mode, 5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // change existing background colors and images to a solid white background. 5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If there's no bg color or image, leave it untouched to avoid affecting transparency. 5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We don't try to avoid loading the background images, because this style flag is only set 5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // when printing, and at that point we've already loaded the background images anyway. (To avoid 5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // loading the background images we'd have to do this check when applying styles rather than 5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // while rendering.) 5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (forceBackgroundToWhite) { 5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that we can't reuse this variable below because the bgColor might be changed 55709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.alpha(); 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) { 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bgColor = Color::white; 5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) shouldPaintBackgroundImage = false; 5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool colorVisible = bgColor.alpha(); 5655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fast path for drawing simple color backgrounds. 5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isRoot && !clippedWithLocalScrolling && !shouldPaintBackgroundImage && isBorderFill && !bgLayer->next()) { 5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!colorVisible) 5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); 5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground); 5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (boxShadowShouldBeAppliedToBackground) 5747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch applyBoxShadowForBackground(context, this); 5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 576d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (hasRoundedBorder && bleedAvoidance != BackgroundBleedClipBackground) { 577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RoundedRect border = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge); 578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (border.isRenderable()) 5795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) context->fillRoundedRect(border, bgColor); 580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else { 581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->save(); 582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clipRoundedInnerRect(context, rect, border); 5835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) context->fillRect(border.rect(), bgColor); 584926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) context->restore(); 585926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 5865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } else { 5875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) context->fillRect(pixelSnappedIntRect(rect), bgColor); 5885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 5895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 593d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // BorderFillBox radius clipping is taken care of by BackgroundBleedClipBackground 594d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedClipBackground); 5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver clipToBorderStateSaver(*context, clipToBorderRadius); 5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipToBorderRadius) { 597926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge); 5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clip to the padding or content boxes as necessary. 6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bgLayer->clip() == ContentFillBox) { 6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) border = style()->getRoundedInnerBorderFor(border.rect(), 6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), includeLeftEdge, includeRightEdge); 6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (bgLayer->clip() == PaddingFillBox) 6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) border = style()->getRoundedInnerBorderFor(border.rect(), includeLeftEdge, includeRightEdge); 6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipRoundedInnerRect(context, rect, border); 6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 60802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int bLeft = includeLeftEdge ? borderLeft() : 0; 6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int bRight = includeRightEdge ? borderRight() : 0; 6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : LayoutUnit(); 6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit pRight = includeRightEdge ? paddingRight() : LayoutUnit(); 6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithLocalScrolling); 6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect scrolledPaintRect = rect; 6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clippedWithLocalScrolling) { 6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clip to the overflow area. 6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBox* thisBox = toRenderBox(this); 61909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->clip(thisBox->overflowClipRect(rect.location())); 62002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Adjust the paint rect to reflect a scrolled content box with borders at the ends. 6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize offset = thisBox->scrolledContentOffset(); 6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scrolledPaintRect.move(-offset); 6241e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) scrolledPaintRect.setWidth(bLeft + thisBox->scrollWidth() + bRight); 6251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) scrolledPaintRect.setHeight(borderTop() + thisBox->scrollHeight() + borderBottom()); 6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 62702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver backgroundClipStateSaver(*context, false); 6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect maskRect; 6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 63193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) switch (bgLayer->clip()) { 63293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) case PaddingFillBox: 63393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) case ContentFillBox: { 63493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (clipToBorderRadius) 63593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 63693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clip to the padding or content boxes as necessary. 63893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bool includePadding = bgLayer->clip() == ContentFillBox; 63993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : LayoutUnit()), 64093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : LayoutUnit()), 64193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : LayoutUnit()), 64293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : LayoutUnit())); 64393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) backgroundClipStateSaver.save(); 64493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) context->clip(clipRect); 64593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 64693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 64793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 64893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) case TextFillBox: { 6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // First figure out how big the mask has to be. It should be no bigger than what we need 6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // to actually render, so we should intersect the dirty rect with the border box of the background. 6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maskRect = pixelSnappedIntRect(rect); 6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maskRect.intersect(paintInfo.rect); 6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 65493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // We draw the background into a separate layer, to be later masked with yet another layer 65593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // holding the text content. 6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) backgroundClipStateSaver.save(); 6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->clip(maskRect); 6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->beginTransparencyLayer(1); 65993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 66093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 66193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 66293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) case BorderFillBox: 66393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 66493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) default: 66593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ASSERT_NOT_REACHED(); 66693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) break; 6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with 6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // no background in the child document should show the parent's background. 6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isOpaqueRoot = false; 6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isRoot) { 6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) isOpaqueRoot = true; 67409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!bgLayer->next() && bgColor.hasAlpha() && view()->frameView()) { 6758abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) Element* ownerElement = document().ownerElement(); 6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ownerElement) { 677d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!isHTMLFrameElement(*ownerElement)) { 6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Locate the <body> element using the DOM. This is easier than trying 6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // to crawl around a render tree with potential :before/:after content and 6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // anonymous blocks created by inline <body> tags etc. We can locate the <body> 6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // render object very easily via the DOM. 6828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) HTMLElement* body = document().body(); 6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (body) { 6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Can't scroll a frameset document anyway. 6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) isOpaqueRoot = body->hasLocalName(framesetTag); 68693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else { 6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // SVG documents and XML documents with SVG root nodes are transparent. 6888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) isOpaqueRoot = !document().hasSVGRootNode(); 6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) isOpaqueRoot = !view()->frameView()->isTransparent(); 6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) view()->frameView()->setContentIsOpaque(isOpaqueRoot); 6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Paint the color first underneath all images, culled if background image occludes it. 698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culling test 699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // by verifying whether the background image covers the entire layout rect. 7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bgLayer->next()) { 7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); 7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); 70307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer->hasOpaqueImage(this) || !bgLayer->hasRepeatXY() || (isOpaqueRoot && !toRenderBox(this)->height())) { 704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!boxShadowShouldBeAppliedToBackground) 705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) backgroundRect.intersect(paintInfo.rect); 706926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground); 708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (boxShadowShouldBeAppliedToBackground) 7097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch applyBoxShadowForBackground(context, this); 7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 71109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (isOpaqueRoot) { 71209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // If we have an alpha and we are painting the root element, go ahead and blend with the base background color. 71309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) Color baseColor = view()->frameView()->baseBackgroundColor(); 71409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool shouldClearDocumentBackground = document().settings() && document().settings()->shouldClearDocumentBackground(); 71509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CompositeOperator operation = shouldClearDocumentBackground ? CompositeCopy : context->compositeOperation(); 71609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 71709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (baseColor.alpha()) { 71809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (bgColor.alpha()) 71909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) baseColor = baseColor.blend(bgColor); 72009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRect(backgroundRect, baseColor, operation); 72109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else if (bgColor.alpha()) { 72209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRect(backgroundRect, bgColor, operation); 72309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else if (shouldClearDocumentBackground) { 72409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->clearRect(backgroundRect); 72509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 726926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (bgColor.alpha()) { 72709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRect(backgroundRect, bgColor, context->compositeOperation()); 72809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // no progressive loading of the background image 7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldPaintBackgroundImage) { 7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BackgroundImageGeometry geometry; 735aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch calculateBackgroundImageGeometry(paintInfo.paintContainer(), bgLayer, scrolledPaintRect, geometry, backgroundObject); 7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.clip(paintInfo.rect); 7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!geometry.destRect().isEmpty()) { 7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op; 7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; 7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geometry.tileSize()); 74143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image.get(), bgLayer, geometry.tileSize()); 7421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (bgLayer->maskSourceType() == MaskLuminance) 7431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) context->setColorFilter(ColorFilterLuminanceToAlpha); 74443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); 74543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) context->setImageInterpolationQuality(interpolationQuality); 7465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) context->drawTiledImage(image.get(), geometry.destRect(), geometry.relativePhase(), geometry.tileSize(), 74743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) compositeOp, bgLayer->blendMode(), geometry.spaceSize()); 74843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) context->setImageInterpolationQuality(previousInterpolationQuality); 7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bgLayer->clip() == TextFillBox) { 75393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Create the text mask layer. 75493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) context->setCompositeOperation(CompositeDestinationIn); 75593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) context->beginTransparencyLayer(1); 75693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 75793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // FIXME: Workaround for https://code.google.com/p/skia/issues/detail?id=1291. 75893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) context->clearRect(maskRect); 75993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 76093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Now draw the text into the mask. We do this by painting using a special paint phase that signals to 76193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // InlineTextBoxes that they should just add their contents to the clip. 76209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForceBlackText, 0); 76393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) context->setCompositeOperation(CompositeSourceOver); 76493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (box) { 765d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RootInlineBox& root = box->root(); 766d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom()); 76793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } else { 76893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset() : LayoutSize(); 76993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) paint(info, scrolledPaintRect.location() - localOffset); 77093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 77193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 772c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) context->endLayer(); 773c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) context->endLayer(); 7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio) 7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height()); 7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio) 7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width()); 7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline IntSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const IntSize& size, const FloatSize& intrinsicRatio, int useWidth, int useHeight) 7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (intrinsicRatio.isEmpty()) { 7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (useWidth) 7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(useWidth, size.height()); 7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(size.width(), useHeight); 7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (useWidth) 7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio)); 7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight); 7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const FloatSize& intrinsicRatio) 8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Two possible solutions: (size.width(), solutionHeight) or (solutionWidth, size.height()) 8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // "... must be assumed to be the largest dimensions..." = easiest answer: the rect with the largest surface area. 8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio); 8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio); 8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (solutionWidth <= size.width()) { 8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (solutionHeight <= size.height()) { 8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If both solutions fit, choose the one covering the larger area. 8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int areaOne = solutionWidth * size.height(); 8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int areaTwo = size.width() * solutionHeight; 8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (areaOne < areaTwo) 8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(size.width(), solutionHeight); 8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(solutionWidth, size.height()); 8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only the first solution fits. 8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(solutionWidth, size.height()); 8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only the second solution fits, assert that. 8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(solutionHeight <= size.height()); 8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(size.width(), solutionHeight); 8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const 8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A generated image without a fixed size, will always return the container size as intrinsic size. 8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (image->isGeneratedImage() && image->usesImageContainerSize()) 8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(positioningAreaSize.width(), positioningAreaSize.height()); 8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Length intrinsicWidth; 8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Length intrinsicHeight; 8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize intrinsicRatio; 8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio); 8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 83710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(!intrinsicWidth.isPercent()); 83810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(!intrinsicHeight.isPercent()); 8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 84010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch IntSize resolvedSize(intrinsicWidth.value(), intrinsicHeight.value()); 8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0); 8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldScaleOrNot == ScaleByEffectiveZoom) 8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resolvedSize.scale(style()->effectiveZoom()); 8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resolvedSize.clampToMinimumSize(minimumSize); 8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!resolvedSize.isEmpty()) 8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return resolvedSize; 8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the image has one of either an intrinsic width or an intrinsic height: 8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // * and an intrinsic aspect ratio, then the missing dimension is calculated from the given dimension and the ratio. 8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // * and no intrinsic aspect ratio, then the missing dimension is assumed to be the size of the rectangle that 8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // establishes the coordinate system for the 'background-position' property. 8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (resolvedSize.width() > 0 || resolvedSize.height() > 0) 8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedSize.width(), resolvedSize.height()); 8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the image has no intrinsic dimensions and has an intrinsic ratio the dimensions must be assumed to be the 8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that 8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // establishes the coordinate system for the 'background-position' property. 8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!intrinsicRatio.isEmpty()) 8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio); 8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the image has no intrinsic ratio either, then the dimensions must be assumed to be the rectangle that 8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // establishes the coordinate system for the 'background-position' property. 8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return positioningAreaSize; 8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize) 8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tileSize.width().ceil() : tileSize.width().floor()); 8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? tileSize.height().ceil() : tileSize.height().floor()); 8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, const IntSize& positioningAreaSize) const 8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StyleImage* image = fillLayer->image(); 8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EFillSizeType type = fillLayer->size().type; 8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize, ScaleByEffectiveZoom); 8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScaleFactor()); 8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (type) { 8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SizeLength: { 8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutSize tileSize = positioningAreaSize; 8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Length layerWidth = fillLayer->size().size.width(); 8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Length layerHeight = fillLayer->size().size.height(); 8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (layerWidth.isFixed()) 8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setWidth(layerWidth.value()); 88909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (layerWidth.isPercent()) 89009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.width())); 89102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (layerHeight.isFixed()) 8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setHeight(layerHeight.value()); 89409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else if (layerHeight.isPercent()) 89509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.height())); 8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize); 8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If one of the values is auto we have to use the appropriate 9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // scale to maintain our aspect ratio. 9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (layerWidth.isAuto() && !layerHeight.isAuto()) { 9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (imageIntrinsicSize.height()) 9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setWidth(imageIntrinsicSize.width() * tileSize.height() / imageIntrinsicSize.height()); 9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (!layerWidth.isAuto() && layerHeight.isAuto()) { 9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (imageIntrinsicSize.width()) 9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.setHeight(imageIntrinsicSize.height() * tileSize.width() / imageIntrinsicSize.width()); 9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (layerWidth.isAuto() && layerHeight.isAuto()) { 9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If both width and height are auto, use the image's intrinsic size. 9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize = imageIntrinsicSize; 9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 91102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) tileSize.clampNegativeToZero(); 9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return flooredIntSize(tileSize); 9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case SizeNone: { 9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any. 9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!imageIntrinsicSize.isEmpty()) 9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return imageIntrinsicSize; 9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for ‘contain’. 9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) type = Contain; 9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Contain: 9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Cover: { 9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float horizontalScaleFactor = imageIntrinsicSize.width() 9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ? static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width() : 1; 9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float verticalScaleFactor = imageIntrinsicSize.height() 9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height() : 1; 9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float scaleFactor = type == Contain ? min(horizontalScaleFactor, verticalScaleFactor) : max(horizontalScaleFactor, verticalScaleFactor); 93006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) return IntSize(max(1l, lround(imageIntrinsicSize.width() * scaleFactor)), max(1l, lround(imageIntrinsicSize.height() * scaleFactor))); 9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntSize(); 9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX(int xOffset) 9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destRect.move(max(xOffset, 0), 0); 9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_phase.setX(-min(xOffset, 0)); 9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destRect.setWidth(m_tileSize.width() + min(xOffset, 0)); 9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY(int yOffset) 9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destRect.move(0, max(yOffset, 0)); 9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_phase.setY(-min(yOffset, 0)); 9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destRect.setHeight(m_tileSize.height() + min(yOffset, 0)); 9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment(const IntPoint& attachmentPoint) 9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntPoint alignedPoint = attachmentPoint; 9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_phase.move(max(alignedPoint.x() - m_destRect.x(), 0), max(alignedPoint.y() - m_destRect.y(), 0)); 9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::BackgroundImageGeometry::clip(const IntRect& clipRect) 9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destRect.intersect(clipRect); 9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntPoint RenderBoxModelObject::BackgroundImageGeometry::relativePhase() const 9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntPoint phase = m_phase; 9655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) phase += m_destRect.location() - m_destOrigin; 9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return phase; 9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const 970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 9716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (!isDocumentElement()) 972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers) 975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RenderLayer* rootLayer = view()->layer(); 978bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (!rootLayer || rootLayer->compositingState() == NotComposited) 979926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return false; 980926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 9811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) return rootLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground(); 9821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)} 9831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 9841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static inline int getSpace(int areaSize, int tileSize) 9851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){ 9861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int numberOfTiles = areaSize / tileSize; 9871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int space = -1; 9881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 9891e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (numberOfTiles > 1) 9901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) space = lroundf((float)(areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1)); 9911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 9921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) return space; 993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 995aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochvoid RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer* fillLayer, const LayoutRect& paintRect, 996aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const 9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit left = 0; 9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit top = 0; 10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize positioningAreaSize; 10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect snappedPaintRect = pixelSnappedIntRect(paintRect); 10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Determine the background positioning area and set destRect to the background painting area. 10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // destRect will be adjusted later if the background is non-repeating. 1005aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch // FIXME: transforms spec says that fixed backgrounds behave like scroll inside transforms. 10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment; 100709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (RuntimeEnabledFeatures::fastMobileScrollingEnabled() 10095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) && view()->frameView() 10105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) && view()->frameView()->shouldAttemptToScrollUsingFastPath()) { 101109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // As a side effect of an optimization to blit on scroll, we do not honor the CSS 101209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // property "background-attachment: fixed" because it may result in rendering 101309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // artifacts. Note, these artifacts only appear if we are blitting on scroll of 101409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // a page that has fixed background images. 101509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) fixedAttachment = false; 101609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 101709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fixedAttachment) { 10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.setDestRect(snappedPaintRect); 10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit right = 0; 10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit bottom = 0; 10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Scroll and Local. 10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fillLayer->origin() != BorderFillBox) { 10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left = borderLeft(); 10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) right = borderRight(); 10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top = borderTop(); 10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottom = borderBottom(); 10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fillLayer->origin() == ContentFillBox) { 10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left += paddingLeft(); 10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) right += paddingRight(); 10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top += paddingTop(); 10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottom += paddingBottom(); 10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The background of the box generated by the root element covers the entire canvas including 10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // its margins. Since those were added in already, we have to factor them out when computing 10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the background positioning area. 10406f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (isDocumentElement()) { 10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) positioningAreaSize = pixelSnappedIntSize(toRenderBox(this)->size() - LayoutSize(left + right, top + bottom), toRenderBox(this)->location()); 10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) left += marginLeft(); 10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) top += marginTop(); 10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutSize(left + right, top + bottom), paintRect.location()); 10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1047aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch geometry.setHasNonLocalGeometry(); 1048aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 1049926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) IntRect viewportRect = pixelSnappedIntRect(viewRect()); 1050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (fixedBackgroundPaintsInLocalCoordinates()) 1051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) viewportRect.setLocation(IntPoint()); 1052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) else if (FrameView* frameView = view()->frameView()) 1053926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition())); 105402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1055aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch if (paintContainer) { 1056aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->localToAbsolute(FloatPoint())); 1057aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch viewportRect.moveBy(-absoluteContainerOffset); 1058aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch } 1059aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 1060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) geometry.setDestRect(pixelSnappedIntRect(viewportRect)); 10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) positioningAreaSize = geometry.destRect().size(); 10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1064aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch const RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; 10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize fillTileSize = calculateFillTileSize(fillLayer, positioningAreaSize); 1066926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) fillLayer->image()->setContainerSizeForRenderer(clientForBackgroundImage, fillTileSize, style()->effectiveZoom()); 10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.setTileSize(fillTileSize); 10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EFillRepeat backgroundRepeatX = fillLayer->repeatX(); 10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EFillRepeat backgroundRepeatY = fillLayer->repeatY(); 1071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int availableWidth = positioningAreaSize.width() - geometry.tileSize().width(); 1072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int availableHeight = positioningAreaSize.height() - geometry.tileSize().height(); 10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 107409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer->xPosition(), availableWidth); 1075e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fillTileSize.width() > 0) { 10761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) long nrTiles = max(1l, lroundf((float)positioningAreaSize.width() / fillTileSize.width())); 1077e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 1078e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (fillLayer->size().size.height().isAuto() && backgroundRepeatY != RoundFill) { 1079e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.width() / (nrTiles * fillTileSize.width())); 1080e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 1081e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 1082e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) fillTileSize.setWidth(positioningAreaSize.width() / nrTiles); 1083e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) geometry.setTileSize(fillTileSize); 1084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0); 10851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize()); 1086e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 1087e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 108809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer->yPosition(), availableHeight); 1089e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > 0 && fillTileSize.height() > 0) { 10901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) long nrTiles = max(1l, lroundf((float)positioningAreaSize.height() / fillTileSize.height())); 1091e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 1092e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (fillLayer->size().size.width().isAuto() && backgroundRepeatX != RoundFill) { 1093e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.height() / (nrTiles * fillTileSize.height())); 1094e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 1095e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 1096e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) fillTileSize.setHeight(positioningAreaSize.height() / nrTiles); 1097e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) geometry.setTileSize(fillTileSize); 1098e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0); 10991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize()); 1100e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 1101e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 1102e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (backgroundRepeatX == RepeatFill) { 1103e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0); 11041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize()); 11051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > 0) { 11061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int space = getSpace(positioningAreaSize.width(), geometry.tileSize().width()); 11071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int actualWidth = geometry.tileSize().width() + space; 11081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 11091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (space >= 0) { 111009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) computedXPosition = roundedMinimumValueForLength(Length(), availableWidth); 11111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize(space, 0)); 11121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setPhaseX(actualWidth ? actualWidth - roundToInt(computedXPosition + left) % actualWidth : 0); 11131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } else { 11141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) backgroundRepeatX = NoRepeatFill; 11151e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 11161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 11171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (backgroundRepeatX == NoRepeatFill) { 1118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int xOffset = fillLayer->backgroundXOrigin() == RightEdge ? availableWidth - computedXPosition : computedXPosition; 1119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) geometry.setNoRepeatX(left + xOffset); 11201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize(0, geometry.spaceSize().height())); 1121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 11221e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 1123e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (backgroundRepeatY == RepeatFill) { 1124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0); 11251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), 0)); 11261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > 0) { 11271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int space = getSpace(positioningAreaSize.height(), geometry.tileSize().height()); 11281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) int actualHeight = geometry.tileSize().height() + space; 11291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 11301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (space >= 0) { 113109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) computedYPosition = roundedMinimumValueForLength(Length(), availableHeight); 11321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), space)); 11331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setPhaseY(actualHeight ? actualHeight - roundToInt(computedYPosition + top) % actualHeight : 0); 11341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } else { 11351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) backgroundRepeatY = NoRepeatFill; 11361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 11371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 11381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (backgroundRepeatY == NoRepeatFill) { 1139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int yOffset = fillLayer->backgroundYOrigin() == BottomEdge ? availableHeight - computedYPosition : computedYPosition; 1140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) geometry.setNoRepeatY(top + yOffset); 11411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) geometry.setSpaceSize(IntSize(geometry.spaceSize().width(), 0)); 1142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fixedAttachment) 11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.useFixedAttachment(snappedPaintRect.location()); 11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.clip(snappedPaintRect); 11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) geometry.setDestOrigin(geometry.destRect().location()); 11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 115109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static LayoutUnit computeBorderImageSide(const BorderImageLength& borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent) 11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 115351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (borderSlice.isNumber()) 115451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return borderSlice.number() * borderSide; 115551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (borderSlice.length().isAuto()) 11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return imageSide; 115709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return valueForLength(borderSlice.length(), boxExtent); 11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style, 11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const NinePieceImage& ninePieceImage, CompositeOperator op) 11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StyleImage* styleImage = ninePieceImage.image(); 11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!styleImage) 11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!styleImage->isLoaded()) 11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either. 11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 117010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (!styleImage->canRender(*this, style->effectiveZoom())) 11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function 11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // doesn't have any understanding of the zoom that is in effect on the tile. 11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect rectWithOutsets = rect; 11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rectWithOutsets.expand(style->imageOutsets(ninePieceImage)); 11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect borderImageRect = pixelSnappedIntRect(rectWithOutsets); 11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize imageSize = calculateImageIntrinsicDimensions(styleImage, borderImageRect.size(), DoNotScaleByEffectiveZoom); 11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any. 11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) styleImage->setContainerSizeForRenderer(this, imageSize, style->effectiveZoom()); 11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int imageWidth = imageSize.width(); 11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int imageHeight = imageSize.height(); 11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float imageScaleFactor = styleImage->imageScaleFactor(); 118809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int topSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight)) * imageScaleFactor; 118909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int rightSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth)) * imageScaleFactor; 119009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int bottomSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight)) * imageScaleFactor; 119109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int leftSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth)) * imageScaleFactor; 11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ENinePieceImageRule hRule = ninePieceImage.horizontalRule(); 11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ENinePieceImageRule vRule = ninePieceImage.verticalRule(); 11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 119609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height()); 119709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width()); 119809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height()); 119909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width()); 12005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Reduce the widths if they're too large. 12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The spec says: Given Lwidth as the width of the border image area, Lheight as its height, and Wside as the border image width 12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // offset for the side, let f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all W are reduced by 12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // multiplying them by f. 12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int borderSideWidth = max(1, leftWidth + rightWidth); 12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int borderSideHeight = max(1, topWidth + bottomWidth); 12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float borderSideScaleFactor = min((float)borderImageRect.width() / borderSideWidth, (float)borderImageRect.height() / borderSideHeight); 12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (borderSideScaleFactor < 1) { 12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) topWidth *= borderSideScaleFactor; 12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rightWidth *= borderSideScaleFactor; 12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomWidth *= borderSideScaleFactor; 12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) leftWidth *= borderSideScaleFactor; 12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawLeft = leftSlice > 0 && leftWidth > 0; 12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawTop = topSlice > 0 && topWidth > 0; 12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawRight = rightSlice > 0 && rightWidth > 0; 12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawBottom = bottomSlice > 0 && bottomWidth > 0; 12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool drawMiddle = ninePieceImage.fill() && (imageWidth - leftSlice - rightSlice) > 0 && (borderImageRect.width() - leftWidth - rightWidth) > 0 12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (imageHeight - topSlice - bottomSlice) > 0 && (borderImageRect.height() - topWidth - bottomWidth) > 0; 12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Image> image = styleImage->image(this, imageSize); 12235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float destinationWidth = borderImageRect.width() - leftWidth - rightWidth; 12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float destinationHeight = borderImageRect.height() - topWidth - bottomWidth; 12265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float sourceWidth = imageWidth - leftSlice - rightSlice; 12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float sourceHeight = imageHeight - topSlice - bottomSlice; 12295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float leftSideScale = drawLeft ? (float)leftWidth / leftSlice : 1; 12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float rightSideScale = drawRight ? (float)rightWidth / rightSlice : 1; 12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float topSideScale = drawTop ? (float)topWidth / topSlice : 1; 12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float bottomSideScale = drawBottom ? (float)bottomWidth / bottomSlice : 1; 12345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawLeft) { 12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the top and bottom left corners. 12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The top left corner rect is (tx, ty, leftWidth, topWidth) 12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice) 12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawTop) 12415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawImage(image.get(), IntRect(borderImageRect.location(), IntSize(leftWidth, topWidth)), 12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect(0, 0, leftSlice, topSlice), op); 12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth) 12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice) 12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawBottom) 12475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawImage(image.get(), IntRect(borderImageRect.x(), borderImageRect.maxY() - bottomWidth, leftWidth, bottomWidth), 12485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op); 12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the left edge. 12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Have to scale and tile into the border rect. 12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sourceHeight > 0) 12535267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.x(), borderImageRect.y() + topWidth, leftWidth, destinationHeight), 12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(0, topSlice, leftSlice, sourceHeight), 12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize(leftSideScale, leftSideScale), Image::StretchTile, (Image::TileRule)vRule, op); 12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawRight) { 12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the top and bottom right corners 12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth) 12615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice) 12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawTop) 12635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawImage(image.get(), IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y(), rightWidth, topWidth), 12645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op); 12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth) 12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice) 12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawBottom) 12695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawImage(image.get(), IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.maxY() - bottomWidth, rightWidth, bottomWidth), 12705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op); 12715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the right edge. 12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sourceHeight > 0) 12745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y() + topWidth, rightWidth, 12755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationHeight), 12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(imageWidth - rightSlice, topSlice, rightSlice, sourceHeight), 12775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize(rightSideScale, rightSideScale), 12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Image::StretchTile, (Image::TileRule)vRule, op); 12795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the top edge. 12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawTop && sourceWidth > 0) 12835267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.x() + leftWidth, borderImageRect.y(), destinationWidth, topWidth), 12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(leftSlice, 0, sourceWidth, topSlice), 12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize(topSideScale, topSideScale), (Image::TileRule)hRule, Image::StretchTile, op); 12865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the bottom edge. 12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawBottom && sourceWidth > 0) 12895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawTiledImage(image.get(), IntRect(borderImageRect.x() + leftWidth, borderImageRect.maxY() - bottomWidth, 12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationWidth, bottomWidth), 12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(leftSlice, imageHeight - bottomSlice, sourceWidth, bottomSlice), 12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize(bottomSideScale, bottomSideScale), 12935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (Image::TileRule)hRule, Image::StretchTile, op); 12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint the middle. 12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawMiddle) { 12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatSize middleScaleFactor(1, 1); 12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawTop) 12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setWidth(topSideScale); 13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (drawBottom) 13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setWidth(bottomSideScale); 13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (drawLeft) 13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setHeight(leftSideScale); 13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (drawRight) 13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setHeight(rightSideScale); 13065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For "stretch" rules, just override the scale factor and replace. We only had to do this for the 13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // center tile, since sides don't even use the scale factor unless they have a rule other than "stretch". 13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The middle however can have "stretch" specified in one axis but not the other, so we have to 13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // correct the scale here. 13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hRule == StretchImageRule) 13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setWidth(destinationWidth / sourceWidth); 13135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 13145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (vRule == StretchImageRule) 13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor.setHeight(destinationHeight / sourceHeight); 13165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 13175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->drawTiledImage(image.get(), 13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(borderImageRect.x() + leftWidth, borderImageRect.y() + topWidth, destinationWidth, destinationHeight), 13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect(leftSlice, topSlice, sourceWidth, sourceHeight), 13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) middleScaleFactor, (Image::TileRule)hRule, (Image::TileRule)vRule, op); 13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class BorderEdge { 13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdge(int edgeWidth, const Color& edgeColor, EBorderStyle edgeStyle, bool edgeIsTransparent, bool edgeIsPresent = true) 13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : width(edgeWidth) 13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , color(edgeColor) 13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , style(edgeStyle) 13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , isTransparent(edgeIsTransparent) 13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , isPresent(edgeIsPresent) 13345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == DOUBLE && edgeWidth < 3) 13365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style = SOLID; 13375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 133802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 13395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdge() 13405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : width(0) 13415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , style(BHIDDEN) 13425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , isTransparent(false) 13435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , isPresent(false) 13445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 134602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 13475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasVisibleColorAndStyle() const { return style > BHIDDEN && !isTransparent; } 13485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool shouldRender() const { return isPresent && width && hasVisibleColorAndStyle(); } 13495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool presentButInvisible() const { return usedWidth() && !hasVisibleColorAndStyle(); } 13505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool obscuresBackgroundEdge(float scale) const 13515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 1352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!isPresent || isTransparent || (width * scale) < 2 || color.hasAlpha() || style == BHIDDEN) 13535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 13545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == DOTTED || style == DASHED) 13565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == DOUBLE) 13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return width >= 5 * scale; // The outer band needs to be >= 2px wide at unit scale. 13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 13625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool obscuresBackground() const 13645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 13655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isPresent || isTransparent || color.hasAlpha() || style == BHIDDEN) 13665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == DOTTED || style == DASHED || style == DOUBLE) 13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int usedWidth() const { return isPresent ? width : 0; } 137502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 13765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void getDoubleBorderStripeWidths(int& outerWidth, int& innerWidth) const 13775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 13785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int fullWidth = usedWidth(); 13795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerWidth = fullWidth / 3; 13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerWidth = fullWidth * 2 / 3; 13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We need certain integer rounding results 13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fullWidth % 3 == 2) 13845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerWidth += 1; 13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fullWidth % 3 == 1) 13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerWidth += 1; 13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 138902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width; 13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Color color; 13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EBorderStyle style; 13935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isTransparent; 13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isPresent; 13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool allCornersClippedOut(const RoundedRect& border, const LayoutRect& clipRect) 13985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 13995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect boundingRect = border.rect(); 14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.contains(boundingRect)) 14015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii radii = border.radii(); 14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect topLeftRect(boundingRect.location(), radii.topLeft()); 14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.intersects(topLeftRect)) 14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect topRightRect(boundingRect.location(), radii.topRight()); 14105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) topRightRect.setX(boundingRect.maxX() - topRightRect.width()); 14115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.intersects(topRightRect)) 14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect bottomLeftRect(boundingRect.location(), radii.bottomLeft()); 14155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomLeftRect.setY(boundingRect.maxY() - bottomLeftRect.height()); 14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.intersects(bottomLeftRect)) 14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect bottomRightRect(boundingRect.location(), radii.bottomRight()); 14205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomRightRect.setX(boundingRect.maxX() - bottomRightRect.width()); 14215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bottomRightRect.setY(boundingRect.maxY() - bottomRightRect.height()); 14225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRect.intersects(bottomRightRect)) 14235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 14265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool borderWillArcInnerEdge(const LayoutSize& firstRadius, const FloatSize& secondRadius) 14295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !firstRadius.isZero() || !secondRadius.isZero(); 14315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum BorderEdgeFlag { 14345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TopBorderEdge = 1 << BSTop, 14355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RightBorderEdge = 1 << BSRight, 14365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BottomBorderEdge = 1 << BSBottom, 14375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LeftBorderEdge = 1 << BSLeft, 14385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AllBorderEdges = TopBorderEdge | BottomBorderEdge | LeftBorderEdge | RightBorderEdge 14395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 14405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline BorderEdgeFlag edgeFlagForSide(BoxSide side) 14425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return static_cast<BorderEdgeFlag>(1 << side); 14445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side) 14475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return flags & edgeFlagForSide(side); 14495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool includesAdjacentEdges(BorderEdgeFlags flags) 14525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (flags & (TopBorderEdge | RightBorderEdge)) == (TopBorderEdge | RightBorderEdge) 14545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (flags & (RightBorderEdge | BottomBorderEdge)) == (RightBorderEdge | BottomBorderEdge) 14555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (flags & (BottomBorderEdge | LeftBorderEdge)) == (BottomBorderEdge | LeftBorderEdge) 14565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (flags & (LeftBorderEdge | TopBorderEdge)) == (LeftBorderEdge | TopBorderEdge); 14575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge) 14605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return firstEdge.color == secondEdge.color; 14625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool styleRequiresClipPolygon(EBorderStyle style) 14655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return style == DOTTED || style == DASHED; // These are drawn with a stroke, so we have to clip to get corner miters. 14675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool borderStyleFillsBorderArea(EBorderStyle style) 14705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !(style == DOTTED || style == DASHED || style == DOUBLE); 14725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool borderStyleHasInnerDetail(EBorderStyle style) 14755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return style == GROOVE || style == RIDGE || style == DOUBLE; 14775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool borderStyleIsDottedOrDashed(EBorderStyle style) 14805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return style == DOTTED || style == DASHED; 14825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// OUTSET darkens the bottom and right (and maybe lightens the top and left) 14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// INSET darkens the top and left (and maybe lightens the bottom and right) 14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool borderStyleHasUnmatchedColorsAtCorner(EBorderStyle style, BoxSide side, BoxSide adjacentSide) 14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These styles match at the top/left and bottom/right. 14895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == INSET || style == GROOVE || style == RIDGE || style == OUTSET) { 14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdgeFlags topRightFlags = edgeFlagForSide(BSTop) | edgeFlagForSide(BSRight); 14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdgeFlags bottomLeftFlags = edgeFlagForSide(BSBottom) | edgeFlagForSide(BSLeft); 14925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdgeFlags flags = edgeFlagForSide(side) | edgeFlagForSide(adjacentSide); 14945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return flags == topRightFlags || flags == bottomLeftFlags; 14955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 14965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 14975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 14985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[]) 15005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[side].shouldRender() != edges[adjacentSide].shouldRender()) 15025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!edgesShareColor(edges[side], edges[adjacentSide])) 15055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !borderStyleHasUnmatchedColorsAtCorner(edges[side].style, side, adjacentSide); 15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool colorNeedsAntiAliasAtCorner(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[]) 15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!edges[side].color.hasAlpha()) 15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[side].shouldRender() != edges[adjacentSide].shouldRender()) 15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!edgesShareColor(edges[side], edges[adjacentSide])) 15205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return borderStyleHasUnmatchedColorsAtCorner(edges[side].style, side, adjacentSide); 15235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 15245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This assumes that we draw in order: top, bottom, left, right. 15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool willBeOverdrawn(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[]) 15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (side) { 15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSTop: 15305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSBottom: 15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[adjacentSide].presentButInvisible()) 15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!edgesShareColor(edges[side], edges[adjacentSide]) && edges[adjacentSide].color.hasAlpha()) 15355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 153602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 15375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!borderStyleFillsBorderArea(edges[adjacentSide].style)) 15385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSLeft: 15435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSRight: 15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // These draw last, so are never overdrawn. 15455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, EBorderStyle style, EBorderStyle adjacentStyle) 15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style == DOUBLE || adjacentStyle == DOUBLE || adjacentStyle == GROOVE || adjacentStyle == RIDGE) 15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjacentStyle)) 15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style != adjacentStyle) 15595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide); 15625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 15635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[], bool allowOverdraw) 15655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((edges[side].isTransparent && edges[adjacentSide].isTransparent) || !edges[adjacentSide].isPresent) 15675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (allowOverdraw && willBeOverdrawn(side, adjacentSide, edges)) 15705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!edgesShareColor(edges[side], edges[adjacentSide])) 15735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 15745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (borderStylesRequireMitre(side, adjacentSide, edges[side].style, edges[adjacentSide].style)) 15765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 157702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 15785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 15795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, 15825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const IntRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path, 15835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor) 15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& edgeToRender = edges[side]; 15865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(edgeToRender.width); 15875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& adjacentEdge1 = edges[adjacentSide1]; 15885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& adjacentEdge2 = edges[adjacentSide2]; 15895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, edges, !antialias); 15915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, edges, !antialias); 159202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 15935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1, edges); 15945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2, edges); 15955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.color; 15975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (path) { 15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*graphicsContext); 16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (innerBorder.isRenderable()) 16015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, adjacentSide1StylesMatch, adjacentSide2StylesMatch); 16025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 16035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipBorderSideForComplexInnerPath(graphicsContext, outerBorder, innerBorder, side, edges); 16045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float thickness = max(max(edgeToRender.width, adjacentEdge1.width), adjacentEdge2.width); 16055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawBoxSideFromPath(graphicsContext, outerBorder.rect(), *path, edges, edgeToRender.width, thickness, side, style, 16065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) colorToPaint, edgeToRender.style, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge); 16075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 16085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool clipForStyle = styleRequiresClipPolygon(edgeToRender.style) && (mitreAdjacentSide1 || mitreAdjacentSide2); 16095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSide1, edges) && mitreAdjacentSide1; 16105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSide2, edges) && mitreAdjacentSide2; 16115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2; 161202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 16135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip); 16145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldClip) { 16155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitreAdjacentSide1); 16165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitreAdjacentSide2); 16175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, !aliasAdjacentSide1, !aliasAdjacentSide2); 16185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since we clipped, no need to draw with a mitre. 16195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mitreAdjacentSide1 = false; 16205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mitreAdjacentSide2 = false; 16215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 162202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 16235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawLineForBoxSide(graphicsContext, sideRect.x(), sideRect.y(), sideRect.maxX(), sideRect.maxY(), side, colorToPaint, edgeToRender.style, 16245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? adjacentEdge2.width : 0, antialias); 16255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 16275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static IntRect calculateSideRect(const RoundedRect& outerBorder, const BorderEdge edges[], int side) 16295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 16305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 16315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width = edges[side].width; 16325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (side == BSTop) 16345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.setHeight(width); 16355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (side == BSBottom) 16365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.shiftYEdgeTo(sideRect.maxY() - width); 16375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (side == BSLeft) 16385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.setWidth(width); 16395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 16405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.shiftXEdgeTo(sideRect.maxX() - width); 16415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return sideRect; 16435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 16445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, 1646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const IntPoint& innerBorderAdjustment, const BorderEdge edges[], BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance, 1647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor) 16485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 16495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool renderRadii = outerBorder.isRounded(); 16505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Path roundedPath; 16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (renderRadii) 16535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) roundedPath.addRoundedRect(outerBorder); 165402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // The inner border adjustment for bleed avoidance mode BackgroundBleedBackgroundOverBorder 1656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // is only applied to sideRect, which is okay since BackgroundBleedBackgroundOverBorder 1657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // is only to be used for solid borders and the shape of the border painted by drawBoxSideFromPath 1658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // only depends on sideRect when painting solid borders. 1659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) { 16615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 1662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sideRect.setHeight(edges[BSTop].width + innerBorderAdjustment.y()); 16635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight())); 16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) { 16695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 1670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width - innerBorderAdjustment.y()); 16715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight())); 16735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) { 16775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 1678926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sideRect.setWidth(edges[BSLeft].width + innerBorderAdjustment.x()); 16795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft())); 16815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 16825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) { 16855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 1686926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width - innerBorderAdjustment.x()); 16875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight())); 16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 16905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment, 1694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const BorderEdge edges[], BorderEdgeFlags edgesToDraw, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias) 16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 169653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // willBeOverdrawn assumes that we draw in order: top, bottom, left, right. 169753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // This is different from BoxSide enum order. 169853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static const BoxSide paintOrder[] = { BSTop, BSBottom, BSLeft, BSRight }; 169953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (edgesToDraw) { 17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Find undrawn edges sharing a color. 17025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Color commonColor; 170302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 17045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdgeFlags commonColorEdgeSet = 0; 170553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (size_t i = 0; i < sizeof(paintOrder) / sizeof(paintOrder[0]); ++i) { 170653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) BoxSide currSide = paintOrder[i]; 17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!includesEdge(edgesToDraw, currSide)) 17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool includeEdge; 17115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!commonColorEdgeSet) { 17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) commonColor = edges[currSide].color; 17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) includeEdge = true; 17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) includeEdge = edges[currSide].color == commonColor; 17165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (includeEdge) 17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) commonColorEdgeSet |= edgeFlagForSide(currSide); 17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && commonColor.hasAlpha(); 17225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (useTransparencyLayer) { 17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->beginTransparencyLayer(static_cast<float>(commonColor.alpha()) / 255); 17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue()); 17255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1727926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) paintBorderSides(graphicsContext, style, outerBorder, innerBorder, innerBorderAdjustment, edges, commonColorEdgeSet, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor); 172802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (useTransparencyLayer) 1730c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) graphicsContext->endLayer(); 173102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edgesToDraw &= ~commonColorEdgeSet; 17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 17355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect& rect, const RenderStyle* style, 17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) 17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 17395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContext* graphicsContext = info.context; 17405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // border-image is not affected by border-radius. 17415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paintNinePieceImage(graphicsContext, rect, style, style->borderImage())) 17425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 17435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (graphicsContext->paintingDisabled()) 17455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdge edges[4]; 17485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getBorderEdgeInfo(edges, style, includeLogicalLeftEdge, includeLogicalRightEdge); 174909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RoundedRect outerBorder = style->getRoundedBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge); 1750926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RoundedRect innerBorder = style->getRoundedInnerBorderFor(borderInnerRectAdjustedForBleedAvoidance(graphicsContext, rect, bleedAvoidance), includeLogicalLeftEdge, includeLogicalRightEdge); 17515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 175210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (outerBorder.rect().isEmpty()) 175310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return; 175410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 17555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool haveAlphaColor = false; 17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool haveAllSolidEdges = true; 17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool haveAllDoubleEdges = true; 17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int numEdgesVisible = 4; 17595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool allEdgesShareColor = true; 1760d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bool allEdgesShareWidth = true; 17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int firstVisibleEdge = -1; 1762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) BorderEdgeFlags edgesToDraw = 0; 17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = BSTop; i <= BSLeft; ++i) { 17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& currEdge = edges[i]; 1766926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1767926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (edges[i].shouldRender()) 1768926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) edgesToDraw |= edgeFlagForSide(static_cast<BoxSide>(i)); 1769926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currEdge.presentButInvisible()) { 17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --numEdgesVisible; 17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) allEdgesShareColor = false; 1773d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) allEdgesShareWidth = false; 17745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 17755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 177602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1777d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!currEdge.shouldRender()) { 17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --numEdgesVisible; 17795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1782d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (firstVisibleEdge == -1) { 17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstVisibleEdge = i; 1784d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else { 1785d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (currEdge.color != edges[firstVisibleEdge].color) 1786d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) allEdgesShareColor = false; 1787d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (currEdge.width != edges[firstVisibleEdge].width) 1788d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) allEdgesShareWidth = false; 1789d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 17905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currEdge.color.hasAlpha()) 17925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) haveAlphaColor = true; 179302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 17945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currEdge.style != SOLID) 17955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) haveAllSolidEdges = false; 17965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currEdge.style != DOUBLE) 17985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) haveAllDoubleEdges = false; 17995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If no corner intersects the clip region, we can pretend outerBorder is 18025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // rectangular to improve performance. 18035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (haveAllSolidEdges && outerBorder.isRounded() && allCornersClippedOut(outerBorder, info.rect)) 18045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerBorder.setRadii(RoundedRect::Radii()); 18055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787 18075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((haveAllSolidEdges || haveAllDoubleEdges) && allEdgesShareColor && innerBorder.isRenderable()) { 18085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fast path for drawing all solid edges and all unrounded double edges 1809d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 18105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (numEdgesVisible == 4 && (outerBorder.isRounded() || haveAlphaColor) 18115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && (haveAllSolidEdges || (!outerBorder.isRounded() && !innerBorder.isRounded()))) { 18125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Path path; 181302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1814d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (outerBorder.isRounded() && allEdgesShareWidth) { 1815d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1816d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Very fast path for single stroked round rect with circular corners 1817d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1818d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) graphicsContext->fillBetweenRoundedRects(outerBorder, innerBorder, edges[firstVisibleEdge].color); 1819d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return; 1820d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 1821d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (outerBorder.isRounded() && bleedAvoidance != BackgroundBleedClipBackground) 18225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRoundedRect(outerBorder); 18235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 18245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRect(outerBorder.rect()); 18255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (haveAllDoubleEdges) { 18275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect innerThirdRect = outerBorder.rect(); 18285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect outerThirdRect = outerBorder.rect(); 18295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int side = BSTop; side <= BSLeft; ++side) { 18305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int outerWidth; 18315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int innerWidth; 18325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[side].getDoubleBorderStripeWidths(outerWidth, innerWidth); 18335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (side == BSTop) { 18355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerThirdRect.shiftYEdgeTo(innerThirdRect.y() + innerWidth); 18365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerThirdRect.shiftYEdgeTo(outerThirdRect.y() + outerWidth); 18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (side == BSBottom) { 18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerThirdRect.setHeight(innerThirdRect.height() - innerWidth); 18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerThirdRect.setHeight(outerThirdRect.height() - outerWidth); 18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (side == BSLeft) { 18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerThirdRect.shiftXEdgeTo(innerThirdRect.x() + innerWidth); 18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerThirdRect.shiftXEdgeTo(outerThirdRect.x() + outerWidth); 18435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 18445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerThirdRect.setWidth(innerThirdRect.width() - innerWidth); 18455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerThirdRect.setWidth(outerThirdRect.width() - outerWidth); 18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect outerThird = outerBorder; 18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect innerThird = innerBorder; 18515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerThird.setRect(innerThirdRect); 18525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerThird.setRect(outerThirdRect); 18535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1854d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (outerThird.isRounded() && bleedAvoidance != BackgroundBleedClipBackground) 18555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRoundedRect(outerThird); 18565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRect(outerThird.rect()); 18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1859d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (innerThird.isRounded() && bleedAvoidance != BackgroundBleedClipBackground) 18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRoundedRect(innerThird); 18615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 18625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRect(innerThird.rect()); 18635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (innerBorder.isRounded()) 18665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRoundedRect(innerBorder); 18675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 18685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRect(innerBorder.rect()); 18697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 18705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setFillRule(RULE_EVENODD); 18715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->setFillColor(edges[firstVisibleEdge].color); 18725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->fillPath(path); 18735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 187402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch } 18755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Avoid creating transparent layers 18765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (haveAllSolidEdges && numEdgesVisible != 4 && !outerBorder.isRounded() && haveAlphaColor) { 18775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Path path; 18785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = BSTop; i <= BSLeft; ++i) { 18805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& currEdge = edges[i]; 18815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currEdge.shouldRender()) { 18825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = calculateSideRect(outerBorder, edges, i); 18835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) path.addRect(sideRect); 18845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setFillRule(RULE_NONZERO); 18885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->setFillColor(edges[firstVisibleEdge].color); 18895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->fillPath(path); 18905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 18915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 18935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 18945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool clipToOuterBorder = outerBorder.isRounded(); 18955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder); 18965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipToOuterBorder) { 18975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clip to the inner and outer radii rects. 1898d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (bleedAvoidance != BackgroundBleedClipBackground) 1899926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) graphicsContext->clipRoundedRect(outerBorder); 19005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787 19015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The inside will be clipped out later (in clipBorderSideForComplexInnerPath) 19021e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (innerBorder.isRenderable() && !innerBorder.isEmpty()) 19035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clipOutRoundedRect(innerBorder); 19045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 19055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If only one edge visible antialiasing doesn't create seams 19075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool antialias = shouldAntialiasLines(graphicsContext) || numEdgesVisible == 1; 1908926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RoundedRect unadjustedInnerBorder = (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? style->getRoundedInnerBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge) : innerBorder; 1909926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) IntPoint innerBorderAdjustment(innerBorder.rect().x() - unadjustedInnerBorder.rect().x(), innerBorder.rect().y() - unadjustedInnerBorder.rect().y()); 19105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (haveAlphaColor) 1911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) paintTranslucentBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias); 19125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 1913926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) paintBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias); 19145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 19155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const LayoutRect& borderRect, const Path& borderPath, const BorderEdge edges[], 19175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) float thickness, float drawThickness, BoxSide side, const RenderStyle* style, Color color, EBorderStyle borderStyle, BackgroundBleedAvoidance bleedAvoidance, 19185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) bool includeLogicalLeftEdge, bool includeLogicalRightEdge) 19195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 19205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (thickness <= 0) 19215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 19225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (borderStyle == DOUBLE && thickness < 3) 19245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) borderStyle = SOLID; 19255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (borderStyle) { 19275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BNONE: 19285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BHIDDEN: 19295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 19305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case DOTTED: 19315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case DASHED: { 19325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->setStrokeColor(color); 19335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 193402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // The stroke is doubled here because the provided path is the 193502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // outside edge of the border so half the stroke is clipped off. 19365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The extra multiplier is so that the clipping mask can antialias 19375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the edges to prevent jaggies. 19385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setStrokeThickness(drawThickness * 2 * 1.1f); 19395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke); 19405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the number of dashes that fit in the path is odd and non-integral then we 19425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // will have an awkwardly-sized dash at the end of the path. To try to avoid that 19435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // here, we simply make the whitespace dashes ever so slightly bigger. 19445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This could be even better if we tried to manipulate the dash offset 19455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and possibly the gapLength to get the corners dash-symmetrical. 19465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float dashLength = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f); 19475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float gapLength = dashLength; 19485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float numberOfDashes = borderPath.length() / dashLength; 19495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Don't try to show dashes if we have less than 2 dashes + 2 gaps. 19505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: should do this test per side. 19515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (numberOfDashes >= 4) { 19525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool evenNumberOfFullDashes = !((int)numberOfDashes % 2); 19535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes); 19545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!evenNumberOfFullDashes && !integralNumberOfDashes) { 19555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float numberOfGaps = numberOfDashes / 2; 19565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gapLength += (dashLength / numberOfGaps); 19575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 19585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DashArray lineDash; 19605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lineDash.append(dashLength); 19615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lineDash.append(gapLength); 19625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setLineDash(lineDash, dashLength); 19635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 196402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 19655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: stroking the border path causes issues with tight corners: 19665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // https://bugs.webkit.org/show_bug.cgi?id=58711 19675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Also, to get the best appearance we should stroke a path between the two borders. 19685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->strokePath(borderPath); 19695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 19705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 19715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case DOUBLE: { 19725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Get the inner border rects for both the outer border line and the inner border line 19735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int outerBorderTopWidth; 19745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int innerBorderTopWidth; 19755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSTop].getDoubleBorderStripeWidths(outerBorderTopWidth, innerBorderTopWidth); 19765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int outerBorderRightWidth; 19785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int innerBorderRightWidth; 19795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSRight].getDoubleBorderStripeWidths(outerBorderRightWidth, innerBorderRightWidth); 19805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int outerBorderBottomWidth; 19825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int innerBorderBottomWidth; 19835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSBottom].getDoubleBorderStripeWidths(outerBorderBottomWidth, innerBorderBottomWidth); 19845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int outerBorderLeftWidth; 19865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int innerBorderLeftWidth; 19875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSLeft].getDoubleBorderStripeWidths(outerBorderLeftWidth, innerBorderLeftWidth); 19885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 19895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Draw inner border line 19905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 19915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*graphicsContext); 19925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect innerClip = style->getRoundedInnerBorderFor(borderRect, 19935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) innerBorderTopWidth, innerBorderBottomWidth, innerBorderLeftWidth, innerBorderRightWidth, 19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) includeLogicalLeftEdge, includeLogicalRightEdge); 199502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) graphicsContext->clipRoundedRect(innerClip); 19975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge); 19985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 19995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Draw outer border line 20015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 20025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*graphicsContext); 20035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect outerRect = borderRect; 2004d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (bleedAvoidance == BackgroundBleedClipBackground) { 20055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerRect.inflate(1); 20065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++outerBorderTopWidth; 20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++outerBorderBottomWidth; 20085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++outerBorderLeftWidth; 20095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++outerBorderRightWidth; 20105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 201102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect outerClip = style->getRoundedInnerBorderFor(outerRect, 20135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outerBorderTopWidth, outerBorderBottomWidth, outerBorderLeftWidth, outerBorderRightWidth, 20145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) includeLogicalLeftEdge, includeLogicalRightEdge); 20155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clipOutRoundedRect(outerClip); 20165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge); 20175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 20195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case RIDGE: 20215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case GROOVE: 20225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 20235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EBorderStyle s1; 20245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EBorderStyle s2; 20255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (borderStyle == GROOVE) { 20265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s1 = INSET; 20275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s2 = OUTSET; 20285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 20295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s1 = OUTSET; 20305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s2 = INSET; 20315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 203202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 20335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint full border 20345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s1, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge); 20355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Paint inner only 20375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*graphicsContext); 20385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit topWidth = edges[BSTop].usedWidth() / 2; 20395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit bottomWidth = edges[BSBottom].usedWidth() / 2; 20405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit leftWidth = edges[BSLeft].usedWidth() / 2; 20415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit rightWidth = edges[BSRight].usedWidth() / 2; 20425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect clipRect = style->getRoundedInnerBorderFor(borderRect, 20445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) topWidth, bottomWidth, leftWidth, rightWidth, 20455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) includeLogicalLeftEdge, includeLogicalRightEdge); 20465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) graphicsContext->clipRoundedRect(clipRect); 20485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s2, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge); 20495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 20505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case INSET: 20525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (side == BSTop || side == BSLeft) 20535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) color = color.dark(); 20545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 20555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case OUTSET: 20565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (side == BSBottom || side == BSRight) 20575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) color = color.dark(); 20585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 20595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: 20605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 20615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->setStrokeStyle(NoStroke); 20645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) graphicsContext->setFillColor(color); 20655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->drawRect(pixelSnappedIntRect(borderRect)); 20665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 20675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContext, const RoundedRect& outerBorder, const RoundedRect& innerBorder, 20695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BoxSide side, bool firstEdgeMatches, bool secondEdgeMatches) 20705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 20715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatPoint quad[4]; 20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const LayoutRect& outerRect = outerBorder.rect(); 20745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const LayoutRect& innerRect = innerBorder.rect(); 20755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 207643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) FloatPoint centerPoint(innerRect.location().x().toFloat() + innerRect.width().toFloat() / 2, innerRect.location().y().toFloat() + innerRect.height().toFloat() / 2); 20775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For each side, create a quad that encompasses all parts of that side that may draw, 20795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // including areas inside the innerBorder. 20805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 20815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 0----------------3 20825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 0 \ / 0 20835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // |\ 1----------- 2 /| 208402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // | 1 1 | 208502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // | | | | 20865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // | | | | 208702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // | 2 2 | 208802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // |/ 1------------2 \| 208902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // 3 / \ 3 20905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 0----------------3 20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // 20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (side) { 20935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSTop: 20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[0] = outerRect.minXMinYCorner(); 20955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[1] = innerRect.minXMinYCorner(); 20965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[2] = innerRect.maxXMinYCorner(); 20975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[3] = outerRect.maxXMinYCorner(); 20985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2099591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().topLeft().isZero()) { 2100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[0], quad[1], 2101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2102591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x() + innerBorder.radii().topLeft().width(), 2103591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y()), 2104591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x(), 2106591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y() + innerBorder.radii().topLeft().height()), 2107591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1]); 2108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2110591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().topRight().isZero()) { 2111591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[3], quad[2], 2112591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x() - innerBorder.radii().topRight().width(), 2114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y()), 2115591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2116591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x(), 2117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y() + innerBorder.radii().topRight().height()), 2118591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2]); 2119591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 21215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSLeft: 21235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[0] = outerRect.minXMinYCorner(); 21245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[1] = innerRect.minXMinYCorner(); 21255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[2] = innerRect.minXMaxYCorner(); 21265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[3] = outerRect.minXMaxYCorner(); 21275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2128591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().topLeft().isZero()) { 2129591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[0], quad[1], 2130591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2131591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x() + innerBorder.radii().topLeft().width(), 2132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y()), 2133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2134591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x(), 2135591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y() + innerBorder.radii().topLeft().height()), 2136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1]); 2137591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().bottomLeft().isZero()) { 2140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[3], quad[2], 2141591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x() + innerBorder.radii().bottomLeft().width(), 2143591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y()), 2144591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2145591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x(), 2146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y() - innerBorder.radii().bottomLeft().height()), 2147591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2]); 2148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 21505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSBottom: 21525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[0] = outerRect.minXMaxYCorner(); 21535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[1] = innerRect.minXMaxYCorner(); 21545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[2] = innerRect.maxXMaxYCorner(); 21555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[3] = outerRect.maxXMaxYCorner(); 21565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2157591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().bottomLeft().isZero()) { 2158591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[0], quad[1], 2159591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x() + innerBorder.radii().bottomLeft().width(), 2161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y()), 2162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2163591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x(), 2164591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y() - innerBorder.radii().bottomLeft().height()), 2165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1]); 2166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2168591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().bottomRight().isZero()) { 2169591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[3], quad[2], 2170591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2171591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x() - innerBorder.radii().bottomRight().width(), 2172591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y()), 2173591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2174591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x(), 2175591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y() - innerBorder.radii().bottomRight().height()), 2176591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2]); 2177591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 21795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSRight: 21815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[0] = outerRect.maxXMinYCorner(); 21825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[1] = innerRect.maxXMinYCorner(); 21835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[2] = innerRect.maxXMaxYCorner(); 21845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quad[3] = outerRect.maxXMaxYCorner(); 21855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2186591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().topRight().isZero()) { 2187591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[0], quad[1], 2188591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2189591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x() - innerBorder.radii().topRight().width(), 2190591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y()), 2191591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2192591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].x(), 2193591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1].y() + innerBorder.radii().topRight().height()), 2194591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[1]); 2195591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 21965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2197591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (!innerBorder.radii().bottomRight().isZero()) { 2198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch findIntersection(quad[3], quad[2], 2199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2200591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x() - innerBorder.radii().bottomRight().width(), 2201591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y()), 2202591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch FloatPoint( 2203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].x(), 2204591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2].y() - innerBorder.radii().bottomRight().height()), 2205591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch quad[2]); 2206591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 22075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 22085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 22095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the border matches both of its adjacent sides, don't anti-alias the clip, and 22115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // if neither side matches, anti-alias the clip. 22125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (firstEdgeMatches == secondEdgeMatches) { 22135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clipConvexPolygon(4, quad, !firstEdgeMatches); 22145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 22155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 22165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // If antialiasing settings for the first edge and second edge is different, 2218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // they have to be addressed separately. We do this by breaking the quad into 2219591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // two parallelograms, made by moving quad[1] and quad[2]. 2220591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float ax = quad[1].x() - quad[0].x(); 2221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float ay = quad[1].y() - quad[0].y(); 2222591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float bx = quad[2].x() - quad[1].x(); 2223591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float by = quad[2].y() - quad[1].y(); 2224591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float cx = quad[3].x() - quad[2].x(); 2225591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float cy = quad[3].y() - quad[2].y(); 2226591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 2227591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch const static float kEpsilon = 1e-2f; 2228591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch float r1, r2; 2229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (fabsf(bx) < kEpsilon && fabsf(by) < kEpsilon) { 2230591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // The quad was actually a triangle. 2231591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch r1 = r2 = 1.0f; 2232591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } else { 2233591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // Extend parallelogram a bit to hide calculation error 2234591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch const static float kExtendFill = 1e-2f; 2235591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 2236591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch r1 = (-ax * by + ay * bx) / (cx * by - cy * bx) + kExtendFill; 2237591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch r2 = (-cx * by + cy * bx) / (ax * by - ay * bx) + kExtendFill; 2238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch } 2239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 22405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatPoint firstQuad[4]; 22415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstQuad[0] = quad[0]; 22425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstQuad[1] = quad[1]; 2243591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch firstQuad[2] = FloatPoint(quad[3].x() + r2 * ax, quad[3].y() + r2 * ay); 22445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstQuad[3] = quad[3]; 22455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clipConvexPolygon(4, firstQuad, !firstEdgeMatches); 22465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatPoint secondQuad[4]; 22485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) secondQuad[0] = quad[0]; 2249591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); 22505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) secondQuad[2] = quad[2]; 22515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) secondQuad[3] = quad[3]; 22525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clipConvexPolygon(4, secondQuad, !secondEdgeMatches); 22535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 22545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static IntRect calculateSideRectIncludingInner(const RoundedRect& outerBorder, const BorderEdge edges[], BoxSide side) 22565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 22575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect sideRect = outerBorder.rect(); 22585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width; 22595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (side) { 22615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSTop: 22625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = sideRect.height() - edges[BSBottom].width; 22635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.setHeight(width); 22645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 22655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSBottom: 22665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = sideRect.height() - edges[BSTop].width; 22675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.shiftYEdgeTo(sideRect.maxY() - width); 22685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 22695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSLeft: 22705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = sideRect.width() - edges[BSRight].width; 22715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.setWidth(width); 22725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 22735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSRight: 22745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = sideRect.width() - edges[BSLeft].width; 22755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sideRect.shiftXEdgeTo(sideRect.maxX() - width); 22765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 22775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 22785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return sideRect; 22805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 22815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static RoundedRect calculateAdjustedInnerBorder(const RoundedRect&innerBorder, BoxSide side) 22835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 22845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Expand the inner border as necessary to make it a rounded rect (i.e. radii contained within each edge). 22855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This function relies on the fact we only get radii not contained within each edge if one of the radii 22865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // for an edge is zero, so we can shift the arc towards the zero radius corner. 22875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect::Radii newRadii = innerBorder.radii(); 22885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect newRect = innerBorder.rect(); 22895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float overshoot; 22915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float maxRadii; 22925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (side) { 22945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSTop: 22955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) overshoot = newRadii.topLeft().width() + newRadii.topRight().width() - newRect.width(); 22965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (overshoot > 0) { 22975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!(newRadii.topLeft().width() && newRadii.topRight().width())); 22985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setWidth(newRect.width() + overshoot); 22995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!newRadii.topLeft().width()) 23005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(-overshoot, 0); 23015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setBottomLeft(IntSize(0, 0)); 23035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setBottomRight(IntSize(0, 0)); 23045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maxRadii = max(newRadii.topLeft().height(), newRadii.topRight().height()); 23055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (maxRadii > newRect.height()) 23065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setHeight(maxRadii); 23075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 23085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSBottom: 23105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) overshoot = newRadii.bottomLeft().width() + newRadii.bottomRight().width() - newRect.width(); 23115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (overshoot > 0) { 23125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!(newRadii.bottomLeft().width() && newRadii.bottomRight().width())); 23135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setWidth(newRect.width() + overshoot); 23145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!newRadii.bottomLeft().width()) 23155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(-overshoot, 0); 23165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setTopLeft(IntSize(0, 0)); 23185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setTopRight(IntSize(0, 0)); 23195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maxRadii = max(newRadii.bottomLeft().height(), newRadii.bottomRight().height()); 23205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (maxRadii > newRect.height()) { 23215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(0, newRect.height() - maxRadii); 23225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setHeight(maxRadii); 23235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 23255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSLeft: 23275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) overshoot = newRadii.topLeft().height() + newRadii.bottomLeft().height() - newRect.height(); 23285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (overshoot > 0) { 23295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!(newRadii.topLeft().height() && newRadii.bottomLeft().height())); 23305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setHeight(newRect.height() + overshoot); 23315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!newRadii.topLeft().height()) 23325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(0, -overshoot); 23335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setTopRight(IntSize(0, 0)); 23355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setBottomRight(IntSize(0, 0)); 23365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maxRadii = max(newRadii.topLeft().width(), newRadii.bottomLeft().width()); 23375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (maxRadii > newRect.width()) 23385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setWidth(maxRadii); 23395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 23405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BSRight: 23425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) overshoot = newRadii.topRight().height() + newRadii.bottomRight().height() - newRect.height(); 23435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (overshoot > 0) { 23445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!(newRadii.topRight().height() && newRadii.bottomRight().height())); 23455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setHeight(newRect.height() + overshoot); 23465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!newRadii.topRight().height()) 23475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(0, -overshoot); 23485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setTopLeft(IntSize(0, 0)); 23505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRadii.setBottomLeft(IntSize(0, 0)); 23515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) maxRadii = max(newRadii.topRight().width(), newRadii.bottomRight().width()); 23525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (maxRadii > newRect.width()) { 23535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.move(newRect.width() - maxRadii, 0); 23545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newRect.setWidth(maxRadii); 23555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 23575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 23585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return RoundedRect(newRect, newRadii); 23605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 23615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::clipBorderSideForComplexInnerPath(GraphicsContext* graphicsContext, const RoundedRect& outerBorder, const RoundedRect& innerBorder, 23635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BoxSide side, const class BorderEdge edges[]) 23645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 23655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) graphicsContext->clip(calculateSideRectIncludingInner(outerBorder, edges, side)); 23661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) RoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(innerBorder, side); 23671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (!adjustedInnerRect.isEmpty()) 23681e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) graphicsContext->clipOutRoundedRect(adjustedInnerRect); 23695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 23705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const 23725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 23735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool horizontal = style->isHorizontalWritingMode(); 23745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSTop] = BorderEdge(style->borderTopWidth(), 23767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch resolveColor(style, CSSPropertyBorderTopColor), 23775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderTopStyle(), 23785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderTopIsTransparent(), 23795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) horizontal || includeLogicalLeftEdge); 23805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSRight] = BorderEdge(style->borderRightWidth(), 23827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch resolveColor(style, CSSPropertyBorderRightColor), 23835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderRightStyle(), 23845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderRightIsTransparent(), 23855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !horizontal || includeLogicalRightEdge); 23865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSBottom] = BorderEdge(style->borderBottomWidth(), 23887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch resolveColor(style, CSSPropertyBorderBottomColor), 23895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderBottomStyle(), 23905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderBottomIsTransparent(), 23915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) horizontal || includeLogicalRightEdge); 23925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) edges[BSLeft] = BorderEdge(style->borderLeftWidth(), 23947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch resolveColor(style, CSSPropertyBorderLeftColor), 23955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderLeftStyle(), 23965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) style->borderLeftIsTransparent(), 23975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) !horizontal || includeLogicalLeftEdge); 23985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 23995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::borderObscuresBackgroundEdge(const FloatSize& contextScale) const 24015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 24025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdge edges[4]; 24035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getBorderEdgeInfo(edges, style()); 24045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = BSTop; i <= BSLeft; ++i) { 24065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& currEdge = edges[i]; 24075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: for vertical text 24085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float axisScale = (i == BSTop || i == BSBottom) ? contextScale.height() : contextScale.width(); 24095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!currEdge.obscuresBackgroundEdge(axisScale)) 24105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 24145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 24155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::borderObscuresBackground() const 24175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 24185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->hasBorder()) 24195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Bail if we have any border-image for now. We could look at the image alpha to improve this. 24225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style()->borderImage().image()) 24235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BorderEdge edges[4]; 24265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getBorderEdgeInfo(edges, style()); 24275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = BSTop; i <= BSLeft; ++i) { 24295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const BorderEdge& currEdge = edges[i]; 24305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!currEdge.obscuresBackground()) 24315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 24355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 24365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* inlineFlowBox) const 24385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 24395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (bleedAvoidance != BackgroundBleedNone) 24405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (style()->hasAppearance()) 24435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2445f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowList* shadowList = style()->boxShadow(); 2446f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (!shadowList) 2447f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) return false; 2448f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 24495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasOneNormalBoxShadow = false; 2450f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t shadowCount = shadowList->shadows().size(); 2451f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (size_t i = 0; i < shadowCount; ++i) { 2452f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowData& currentShadow = shadowList->shadows()[i]; 2453f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (currentShadow.style() != Normal) 24545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 24555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasOneNormalBoxShadow) 24575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) hasOneNormalBoxShadow = true; 24595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2460f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (currentShadow.spread()) 24615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 24635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!hasOneNormalBoxShadow) 24655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch Color backgroundColor = resolveColor(CSSPropertyBackgroundColor); 246809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (backgroundColor.hasAlpha()) 24695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const FillLayer* lastBackgroundLayer = style()->backgroundLayers(); 24725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (const FillLayer* next = lastBackgroundLayer->next(); next; next = lastBackgroundLayer->next()) 24735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) lastBackgroundLayer = next; 24745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (lastBackgroundLayer->clip() != BorderFillBox) 24765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (lastBackgroundLayer->image() && style()->hasBorderRadius()) 24795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (inlineFlowBox && !inlineFlowBox->boxShadowCanBeAppliedToBackground(*lastBackgroundLayer)) 24825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment) 24855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 24865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 24885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 24895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRect& paintRect, const RenderStyle* s, ShadowStyle shadowStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) 24915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 24925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Deal with border-image. Would be great to use border-image as a mask. 24935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContext* context = info.context; 24945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (context->paintingDisabled() || !s->boxShadow()) 24955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 24965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RoundedRect border = (shadowStyle == Inset) ? s->getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge) 249809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) : s->getRoundedBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge); 24995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool hasBorderRadius = s->hasBorderRadius(); 25015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isHorizontal = s->isHorizontalWritingMode(); 250209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255; 2503e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2504e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) GraphicsContextStateSaver stateSaver(*context, false); 2505f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 2506f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowList* shadowList = s->boxShadow(); 2507f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (size_t i = shadowList->shadows().size(); i--; ) { 2508f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) const ShadowData& shadow = shadowList->shadows()[i]; 2509f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (shadow.style() != shadowStyle) 25105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 25115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 251209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatSize shadowOffset(shadow.x(), shadow.y()); 251309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) float shadowBlur = shadow.blur(); 251409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) float shadowSpread = shadow.spread(); 251502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 25165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shadowOffset.isZero() && !shadowBlur && !shadowSpread) 25175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 251802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 251909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const Color& shadowColor = shadow.color(); 25205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2521f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (shadow.style() == Normal) { 252209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect fillRect = border.rect(); 25235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fillRect.inflate(shadowSpread); 25245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fillRect.isEmpty()) 25255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 25265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 252709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect shadowRect(border.rect()); 25285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) shadowRect.inflate(shadowBlur + shadowSpread); 25295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) shadowRect.move(shadowOffset); 25305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2531e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // Save the state and clip, if not already done. 2532e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // The clip does not depend on any shadow-specific properties. 2533e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (!stateSaver.saved()) { 2534e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) stateSaver.save(); 2535e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (hasBorderRadius) { 2536e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) RoundedRect rectToClipOut = border; 2537e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2538e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time 2539e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // when painting the shadow. On the other hand, it introduces subpixel gaps along the 2540e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // corners. Those are avoided by insetting the clipping path by one pixel. 2541e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (hasOpaqueBackground) 2542e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) rectToClipOut.inflateWithRadii(-1); 2543e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2544e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (!rectToClipOut.isEmpty()) { 2545e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) context->clipOutRoundedRect(rectToClipOut); 2546e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 2547e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } else { 254809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // This IntRect is correct even with fractional shadows, because it is used for the rectangle 254909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // of the box itself, which is always pixel-aligned. 2550e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) IntRect rectToClipOut = border.rect(); 2551e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2552e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time 2553e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // when painting the shadow. On the other hand, it introduces subpixel gaps along the 2554e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path 2555e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // by one pixel. 2556e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (hasOpaqueBackground) { 2557e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // FIXME: The function to decide on the policy based on the transform should be a named function. 2558e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) // FIXME: It's not clear if this check is right. What about integral scale factors? 25595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // FIXME: See crbug.com/382491. The use of getCTM may also be wrong because it does not include 25605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // device zoom applied at raster time. 2561e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) AffineTransform transform = context->getCTM(); 2562e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (transform.a() != 1 || (transform.d() != 1 && transform.d() != -1) || transform.b() || transform.c()) 2563e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) rectToClipOut.inflate(-1); 2564e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 2565e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2566e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) if (!rectToClipOut.isEmpty()) { 2567e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) context->clipOut(rectToClipOut); 2568e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 2569e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 2570e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 2571e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 257293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // Draw only the shadow. 2573d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(); 2574d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) drawLooperBuilder->addShadow(shadowOffset, shadowBlur, shadowColor, 2575d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha); 2576d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) context->setDrawLooper(drawLooperBuilder.release()); 25775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasBorderRadius) { 257909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RoundedRect influenceRect(pixelSnappedIntRect(LayoutRect(shadowRect)), border.radii()); 25805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) influenceRect.expandRadii(2 * shadowBlur + shadowSpread); 25815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (allCornersClippedOut(influenceRect, info.rect)) 258209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRect(fillRect, Color::black); 25835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 258409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // TODO: support non-integer shadows - crbug.com/334829 258509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) RoundedRect roundedFillRect = border; 258609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) roundedFillRect.inflate(shadowSpread); 258709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 258809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) roundedFillRect.expandRadii(shadowSpread); 258909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!roundedFillRect.isRenderable()) 259009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) roundedFillRect.adjustRadii(); 259109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRoundedRect(roundedFillRect, Color::black); 25925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 259409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->fillRect(fillRect, Color::black); 25955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 25965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 259709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // The inset shadow case. 2598591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge; 25995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!includeLogicalLeftEdge) { 2600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch if (isHorizontal) 2601591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch clippedEdges |= GraphicsContext::LeftEdge; 2602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch else 2603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch clippedEdges |= GraphicsContext::TopEdge; 26045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!includeLogicalRightEdge) { 26065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isHorizontal) 2607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch clippedEdges |= GraphicsContext::RightEdge; 26085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch clippedEdges |= GraphicsContext::BottomEdge; 26105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 261109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // TODO: support non-integer shadows - crbug.com/334828 261209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowOffset), shadowBlur, shadowSpread, clippedEdges); 26135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const 26185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 26195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return containingBlock()->availableLogicalWidth(); 26205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderBoxModelObject* RenderBoxModelObject::continuation() const 26235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 26245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!continuationMap) 26255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 26265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return continuationMap->get(this); 26275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation) 26305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 26315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (continuation) { 26325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!continuationMap) 26335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continuationMap = new ContinuationMap; 26345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continuationMap->set(this, continuation); 26355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 26365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (continuationMap) 26375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continuationMap->remove(this); 26385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 26395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochvoid RenderBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) const 26427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch{ 26437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch RenderLayerModelObject::computeLayerHitTestRects(rects); 26447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 26457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch // If there is a continuation then we need to consult it here, since this is 26467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch // the root of the tree walk and it wouldn't otherwise get picked up. 26477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch // Continuations should always be siblings in the tree, so any others should 26487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch // get picked up already by the tree walk. 26497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (continuation()) 26507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch continuation()->computeLayerHitTestRects(rects); 26517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch} 26527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 265351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)RenderTextFragment* RenderBoxModelObject::firstLetterRemainingText() const 26545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 26555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!firstLetterRemainingTextMap) 26565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 26575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return firstLetterRemainingTextMap->get(this); 26585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 266051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void RenderBoxModelObject::setFirstLetterRemainingText(RenderTextFragment* remainingText) 26615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 26625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (remainingText) { 26635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!firstLetterRemainingTextMap) 26645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstLetterRemainingTextMap = new FirstLetterRemainingTextMap; 26655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstLetterRemainingTextMap->set(this, remainingText); 26665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (firstLetterRemainingTextMap) 26675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstLetterRemainingTextMap->remove(this); 26685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 26695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset) 26715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2672d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ASSERT(!slowFirstChild()); 26735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This does not take into account either :first-line or :first-letter 26755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // However, as soon as some content is entered, the line boxes will be 26765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // constructed and this kludge is not called any more. So only the caret size 26775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // of an empty :first-line'd block is wrong. I think we can live with that. 26785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderStyle* currentStyle = firstLineStyle(); 267951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) LayoutUnit height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); 26805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enum CaretAlignment { alignLeft, alignRight, alignCenter }; 26825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CaretAlignment alignment = alignLeft; 26845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (currentStyle->textAlign()) { 26865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case LEFT: 26875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WEBKIT_LEFT: 26885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 26895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case CENTER: 26905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WEBKIT_CENTER: 26915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) alignment = alignCenter; 26925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 26935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case RIGHT: 26945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WEBKIT_RIGHT: 26955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) alignment = alignRight; 26965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 26975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case JUSTIFY: 26985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case TASTART: 26995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!currentStyle->isLeftToRightDirection()) 27005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) alignment = alignRight; 27015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 27025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case TAEND: 27035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currentStyle->isLeftToRightDirection()) 27045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) alignment = alignRight; 27055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 27065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit x = borderLeft() + paddingLeft(); 27095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit maxX = width - borderRight() - paddingRight(); 27105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (alignment) { 27125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case alignLeft: 27135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currentStyle->isLeftToRightDirection()) 27145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x += textIndentOffset; 27155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 27165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case alignCenter: 27175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x = (x + maxX) / 2; 27185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (currentStyle->isLeftToRightDirection()) 27195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x += textIndentOffset / 2; 27205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 27215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x -= textIndentOffset / 2; 27225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 27235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case alignRight: 27245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x = maxX - caretWidth; 27255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!currentStyle->isLeftToRightDirection()) 27265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x -= textIndentOffset; 27275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 27285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x = min(x, max<LayoutUnit>(maxX - caretWidth, 0)); 27305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit y = paddingTop() + borderTop(); 27325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return currentStyle->isHorizontalWritingMode() ? LayoutRect(x, y, caretWidth, height) : LayoutRect(y, x, height, caretWidth); 27345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 27355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context) 27375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 27385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We may want to not antialias when scaled by an integral value, 27395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and we may want to antialias when translated by a non-integral value. 27405d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // FIXME: See crbug.com/382491. getCTM does not include scale factors applied at raster time, such 27415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // as device zoom. 27425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !context->getCTM().isIdentityOrTranslationOrFlipped(); 27435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 27445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const 27465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2747e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) // We don't expect to be called during layout. 27485d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) ASSERT(!view() || !view()->layoutStateCachedOffsetsEnabled()); 2749e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 27505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject* o = container(); 27515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!o) 27525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 27535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2754d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (o->isRenderFlowThread()) 2755d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) transformState.move(o->columnOffset(LayoutPoint(transformState.mappedPoint()))); 27565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 27575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) o->mapAbsoluteToLocalPoint(mode, transformState); 27585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint()); 27605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style()->hasOutOfFlowPosition() && o->hasColumns()) { 2762926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) RenderBlock* block = toRenderBlock(o); 27635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutPoint point(roundedLayoutPoint(transformState.mappedPoint())); 27645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) point -= containerOffset; 27655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) block->adjustForColumnRect(containerOffset, point); 27665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 27675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D()); 27695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { 27705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) TransformationMatrix t; 27715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) getTransformFromContainer(o, containerOffset, t); 27725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); 27735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 27745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); 27755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 27765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2777521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)const RenderObject* RenderBoxModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const 2778521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 2779521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) ASSERT(ancestorToStopAt != this); 2780521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2781521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool ancestorSkipped; 2782521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped); 2783521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (!container) 2784521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) return 0; 2785521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2786521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool isInline = isRenderInline(); 2787521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool isFixedPos = !isInline && style()->position() == FixedPosition; 2788521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool hasTransform = !isInline && hasLayer() && layer()->transform(); 2789521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2790521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) LayoutSize adjustmentForSkippedAncestor; 2791521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (ancestorSkipped) { 2792521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe 2793521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // to just subtract the delta between the ancestor and o. 2794521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container); 2795521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 2796521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2797521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool offsetDependsOnPoint = false; 2798521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint); 2799521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2800521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) bool preserve3D = container->style()->preserves3D() || style()->preserves3D(); 2801521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (shouldUseTransformFromContainer(container)) { 2802521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TransformationMatrix t; 2803521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) getTransformFromContainer(container, containerOffset, t); 2804d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustmentForSkippedAncestor.height().toFloat()); 2805521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform); 2806521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } else { 2807521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) containerOffset += adjustmentForSkippedAncestor; 2808521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform); 2809521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 2810521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 2811521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) return ancestorSkipped ? ancestorToStopAt : container; 2812521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 2813521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 28145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert) 28155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 28165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We assume that callers have cleared their positioned objects list for child moves (!fullRemoveInsert) so the 28175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // positioned renderer maps don't become stale. It would be too slow to do the map lookup on each call. 28185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!fullRemoveInsert || !isRenderBlock() || !toRenderBlock(this)->hasPositionedObjects()); 28195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(this == child->parent()); 28215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); 28225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fullRemoveInsert && (toBoxModelObject->isRenderBlock() || toBoxModelObject->isRenderInline())) { 28235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Takes care of adding the new child correctly if toBlock and fromBlock 28245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // have different kind of children (block vs inline). 28255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) toBoxModelObject->addChild(virtualChildren()->removeChildNode(this, child), beforeChild); 28265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 28275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert); 28285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 28295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert) 28315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 28325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This condition is rarely hit since this function is usually called on 28335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // anonymous blocks which can no longer carry positioned objects (see r120761) 28345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // or when fullRemoveInsert is false. 28355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (fullRemoveInsert && isRenderBlock()) { 28365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBlock* block = toRenderBlock(this); 2837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) block->removePositionedObjects(0); 2838f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (block->isRenderBlockFlow()) 2839f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) toRenderBlockFlow(block)->removeFloatingObjects(); 28405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 28415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); 28435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (RenderObject* child = startChild; child && child != endChild; ) { 28445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Save our next sibling as moveChildTo will clear it. 28455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderObject* nextSibling = child->nextSibling(); 28465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); 28475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) child = nextSibling; 28485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 28495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 28505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 2852