1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2006, 2007, 2009 Apple Inc. All rights reserved.
5 * Copyright (C) 2010 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#pragma once
25
26#include "FontBaseline.h"
27#include "LayoutRect.h"
28#include "RenderLayerModelObject.h"
29
30namespace WebCore {
31
32// Modes for some of the line-related functions.
33enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes };
34enum LineDirectionMode { HorizontalLine, VerticalLine };
35typedef unsigned BorderEdgeFlags;
36
37enum BackgroundBleedAvoidance {
38 BackgroundBleedNone,
39 BackgroundBleedShrinkBackground,
40 BackgroundBleedUseTransparencyLayer,
41 BackgroundBleedBackgroundOverBorder
42};
43
44enum BaseBackgroundColorUsage {
45 BaseBackgroundColorUse,
46 BaseBackgroundColorOnly,
47 BaseBackgroundColorSkip
48};
49
50enum ContentChangeType {
51 ImageChanged,
52 MaskImageChanged,
53 BackgroundImageChanged,
54 CanvasChanged,
55 CanvasPixelsChanged,
56 VideoChanged,
57 FullScreenChanged
58};
59
60class BorderEdge;
61class ImageBuffer;
62class InlineFlowBox;
63class RenderTextFragment;
64class StickyPositionViewportConstraints;
65
66class BackgroundImageGeometry {
67public:
68 BackgroundImageGeometry(const LayoutRect& destinationRect, const LayoutSize& tile, const LayoutSize& phase, const LayoutSize& space, bool fixedAttachment)
69 : m_destRect(destinationRect)
70 , m_destOrigin(m_destRect.location())
71 , m_tileSize(tile)
72 , m_phase(phase)
73 , m_space(space)
74 , m_hasNonLocalGeometry(fixedAttachment)
75 {
76 }
77
78 LayoutRect destRect() const { return m_destRect; }
79 LayoutSize phase() const { return m_phase; }
80 LayoutSize tileSize() const { return m_tileSize; }
81 LayoutSize spaceSize() const { return m_space; }
82 bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; }
83
84 LayoutSize relativePhase() const
85 {
86 LayoutSize phase = m_phase;
87 phase += m_destRect.location() - m_destOrigin;
88 return phase;
89 }
90
91 void clip(const LayoutRect& clipRect) { m_destRect.intersect(clipRect); }
92
93private:
94 LayoutRect m_destRect;
95 LayoutPoint m_destOrigin;
96 LayoutSize m_tileSize;
97 LayoutSize m_phase;
98 LayoutSize m_space;
99 bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
100};
101
102// This class is the base for all objects that adhere to the CSS box model as described
103// at http://www.w3.org/TR/CSS21/box.html
104
105class RenderBoxModelObject : public RenderLayerModelObject {
106 WTF_MAKE_ISO_ALLOCATED(RenderBoxModelObject);
107public:
108 virtual ~RenderBoxModelObject();
109
110 LayoutSize relativePositionOffset() const;
111 LayoutSize relativePositionLogicalOffset() const { return style().isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
112
113 FloatRect constrainingRectForStickyPosition() const;
114 void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& constrainingRect) const;
115 LayoutSize stickyPositionOffset() const;
116 LayoutSize stickyPositionLogicalOffset() const { return style().isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
117
118 LayoutSize offsetForInFlowPosition() const;
119
120 // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
121 // to return the remaining width on a given line (and the height of a single line).
122 virtual LayoutUnit offsetLeft() const;
123 virtual LayoutUnit offsetTop() const;
124 virtual LayoutUnit offsetWidth() const = 0;
125 virtual LayoutUnit offsetHeight() const = 0;
126
127 void updateFromStyle() override;
128
129 bool requiresLayer() const override { return isDocumentElementRenderer() || isPositioned() || createsGroup() || hasClipPath() || hasTransformRelatedProperty() || hasHiddenBackface() || hasReflection(); }
130
131 // This will work on inlines to return the bounding box of all of the lines' border boxes.
132 virtual LayoutRect borderBoundingBox() const = 0;
133
134 // These return the CSS computed padding values.
135 LayoutUnit computedCSSPaddingTop() const { return computedCSSPadding(style().paddingTop()); }
136 LayoutUnit computedCSSPaddingBottom() const { return computedCSSPadding(style().paddingBottom()); }
137 LayoutUnit computedCSSPaddingLeft() const { return computedCSSPadding(style().paddingLeft()); }
138 LayoutUnit computedCSSPaddingRight() const { return computedCSSPadding(style().paddingRight()); }
139 LayoutUnit computedCSSPaddingBefore() const { return computedCSSPadding(style().paddingBefore()); }
140 LayoutUnit computedCSSPaddingAfter() const { return computedCSSPadding(style().paddingAfter()); }
141 LayoutUnit computedCSSPaddingStart() const { return computedCSSPadding(style().paddingStart()); }
142 LayoutUnit computedCSSPaddingEnd() const { return computedCSSPadding(style().paddingEnd()); }
143
144 // These functions are used during layout. Table cells and the MathML
145 // code override them to include some extra intrinsic padding.
146 virtual LayoutUnit paddingTop() const { return computedCSSPaddingTop(); }
147 virtual LayoutUnit paddingBottom() const { return computedCSSPaddingBottom(); }
148 virtual LayoutUnit paddingLeft() const { return computedCSSPaddingLeft(); }
149 virtual LayoutUnit paddingRight() const { return computedCSSPaddingRight(); }
150 virtual LayoutUnit paddingBefore() const { return computedCSSPaddingBefore(); }
151 virtual LayoutUnit paddingAfter() const { return computedCSSPaddingAfter(); }
152 virtual LayoutUnit paddingStart() const { return computedCSSPaddingStart(); }
153 virtual LayoutUnit paddingEnd() const { return computedCSSPaddingEnd(); }
154
155 virtual LayoutUnit borderTop() const { return LayoutUnit(style().borderTopWidth()); }
156 virtual LayoutUnit borderBottom() const { return LayoutUnit(style().borderBottomWidth()); }
157 virtual LayoutUnit borderLeft() const { return LayoutUnit(style().borderLeftWidth()); }
158 virtual LayoutUnit borderRight() const { return LayoutUnit(style().borderRightWidth()); }
159 virtual LayoutUnit horizontalBorderExtent() const { return borderLeft() + borderRight(); }
160 virtual LayoutUnit verticalBorderExtent() const { return borderTop() + borderBottom(); }
161 virtual LayoutUnit borderBefore() const { return LayoutUnit(style().borderBeforeWidth()); }
162 virtual LayoutUnit borderAfter() const { return LayoutUnit(style().borderAfterWidth()); }
163 virtual LayoutUnit borderStart() const { return LayoutUnit(style().borderStartWidth()); }
164 virtual LayoutUnit borderEnd() const { return LayoutUnit(style().borderEndWidth()); }
165
166 LayoutUnit borderAndPaddingStart() const { return borderStart() + paddingStart(); }
167 LayoutUnit borderAndPaddingBefore() const { return borderBefore() + paddingBefore(); }
168 LayoutUnit borderAndPaddingAfter() const { return borderAfter() + paddingAfter(); }
169
170 LayoutUnit verticalBorderAndPaddingExtent() const { return borderTop() + borderBottom() + paddingTop() + paddingBottom(); }
171 LayoutUnit horizontalBorderAndPaddingExtent() const { return borderLeft() + borderRight() + paddingLeft() + paddingRight(); }
172 LayoutUnit borderAndPaddingLogicalHeight() const { return borderAndPaddingBefore() + borderAndPaddingAfter(); }
173 LayoutUnit borderAndPaddingLogicalWidth() const { return borderStart() + borderEnd() + paddingStart() + paddingEnd(); }
174 LayoutUnit borderAndPaddingLogicalLeft() const { return style().isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
175
176 LayoutUnit borderLogicalLeft() const { return style().isHorizontalWritingMode() ? borderLeft() : borderTop(); }
177 LayoutUnit borderLogicalRight() const { return style().isHorizontalWritingMode() ? borderRight() : borderBottom(); }
178 LayoutUnit borderLogicalWidth() const { return borderStart() + borderEnd(); }
179 LayoutUnit borderLogicalHeight() const { return borderBefore() + borderAfter(); }
180
181 LayoutUnit paddingLogicalLeft() const { return style().isHorizontalWritingMode() ? paddingLeft() : paddingTop(); }
182 LayoutUnit paddingLogicalRight() const { return style().isHorizontalWritingMode() ? paddingRight() : paddingBottom(); }
183 LayoutUnit paddingLogicalWidth() const { return paddingStart() + paddingEnd(); }
184 LayoutUnit paddingLogicalHeight() const { return paddingBefore() + paddingAfter(); }
185
186 virtual LayoutUnit marginTop() const = 0;
187 virtual LayoutUnit marginBottom() const = 0;
188 virtual LayoutUnit marginLeft() const = 0;
189 virtual LayoutUnit marginRight() const = 0;
190 virtual LayoutUnit marginBefore(const RenderStyle* otherStyle = nullptr) const = 0;
191 virtual LayoutUnit marginAfter(const RenderStyle* otherStyle = nullptr) const = 0;
192 virtual LayoutUnit marginStart(const RenderStyle* otherStyle = nullptr) const = 0;
193 virtual LayoutUnit marginEnd(const RenderStyle* otherStyle = nullptr) const = 0;
194 LayoutUnit verticalMarginExtent() const { return marginTop() + marginBottom(); }
195 LayoutUnit horizontalMarginExtent() const { return marginLeft() + marginRight(); }
196 LayoutUnit marginLogicalHeight() const { return marginBefore() + marginAfter(); }
197 LayoutUnit marginLogicalWidth() const { return marginStart() + marginEnd(); }
198
199 bool hasInlineDirectionBordersPaddingOrMargin() const { return hasInlineDirectionBordersOrPadding() || marginStart()|| marginEnd(); }
200 bool hasInlineDirectionBordersOrPadding() const { return borderStart() || borderEnd() || paddingStart()|| paddingEnd(); }
201
202 virtual LayoutUnit containingBlockLogicalWidthForContent() const;
203
204 void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle&, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
205 bool paintNinePieceImage(GraphicsContext&, const LayoutRect&, const RenderStyle&, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
206 void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle&, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
207 void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer&, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = nullptr, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderElement* backgroundObject = nullptr, BaseBackgroundColorUsage = BaseBackgroundColorUse);
208
209 virtual bool boxShadowShouldBeAppliedToBackground(const LayoutPoint& absolutePaintPostion, BackgroundBleedAvoidance, InlineFlowBox* = nullptr) const;
210
211 // Overridden by subclasses to determine line height and baseline position.
212 virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
213 virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
214
215 void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const override;
216
217 void setSelectionState(SelectionState) override;
218
219 bool canHaveBoxInfoInFragment() const { return !isFloating() && !isReplaced() && !isInline() && !isTableCell() && isRenderBlock() && !isRenderSVGBlock(); }
220
221 void getGeometryForBackgroundImage(const RenderLayerModelObject* paintContainer, const LayoutPoint& paintOffset, FloatRect& destRect, FloatSize& phase, FloatSize& tileSize) const;
222 void contentChanged(ContentChangeType);
223 bool hasAcceleratedCompositing() const;
224
225 RenderBoxModelObject* continuation() const;
226 WEBCORE_EXPORT RenderInline* inlineContinuation() const;
227
228 void insertIntoContinuationChainAfter(RenderBoxModelObject&);
229 void removeFromContinuationChain();
230
231 virtual LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) { return LayoutRect(); };
232
233 bool hasRunningAcceleratedAnimations() const;
234
235 virtual Optional<LayoutUnit> overrideContainingBlockContentWidth() const { ASSERT_NOT_REACHED(); return -1_lu; }
236 virtual Optional<LayoutUnit> overrideContainingBlockContentHeight() const { ASSERT_NOT_REACHED(); return -1_lu; }
237 virtual bool hasOverrideContainingBlockContentWidth() const { return false; }
238 virtual bool hasOverrideContainingBlockContentHeight() const { return false; }
239
240protected:
241 RenderBoxModelObject(Element&, RenderStyle&&, BaseTypeFlags);
242 RenderBoxModelObject(Document&, RenderStyle&&, BaseTypeFlags);
243
244 void willBeDestroyed() override;
245
246 LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const;
247
248 bool hasVisibleBoxDecorationStyle() const;
249 BackgroundImageGeometry calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer&, const LayoutPoint& paintOffset,
250 const LayoutRect& paintRect, RenderElement* = nullptr) const;
251 bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
252 bool borderObscuresBackground() const;
253 RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
254 LayoutRect borderInnerRectAdjustedForBleedAvoidance(const GraphicsContext&, const LayoutRect&, BackgroundBleedAvoidance) const;
255
256 InterpolationQuality chooseInterpolationQuality(GraphicsContext&, Image&, const void*, const LayoutSize&);
257
258 LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
259
260 static bool shouldAntialiasLines(GraphicsContext&);
261
262 static void clipRoundedInnerRect(GraphicsContext&, const FloatRect&, const FloatRoundedRect& clipRect);
263
264 bool hasAutoHeightOrContainingBlockWithAutoHeight() const;
265
266 DecodingMode decodingModeForImageDraw(const Image&, const PaintInfo&) const;
267
268public:
269 // For RenderBlocks and RenderInlines with m_style->styleType() == PseudoId::FirstLetter, this tracks their remaining text fragments
270 RenderTextFragment* firstLetterRemainingText() const;
271 void setFirstLetterRemainingText(RenderTextFragment&);
272 void clearFirstLetterRemainingText();
273
274 enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
275 LayoutSize calculateImageIntrinsicDimensions(StyleImage*, const LayoutSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
276
277 RenderBlock* containingBlockForAutoHeightDetection(Length logicalHeight) const;
278
279 struct ContinuationChainNode {
280 WeakPtr<RenderBoxModelObject> renderer;
281 ContinuationChainNode* previous { nullptr };
282 ContinuationChainNode* next { nullptr };
283
284 ContinuationChainNode(RenderBoxModelObject&);
285 ~ContinuationChainNode();
286
287 void insertAfter(ContinuationChainNode&);
288
289 WTF_MAKE_FAST_ALLOCATED;
290 };
291
292 ContinuationChainNode* continuationChainNode() const;
293
294protected:
295 LayoutUnit computedCSSPadding(const Length&) const;
296
297private:
298 ContinuationChainNode& ensureContinuationChainNode();
299
300 virtual LayoutRect frameRectForStickyPositioning() const = 0;
301
302 LayoutSize calculateFillTileSize(const FillLayer&, const LayoutSize& scaledPositioningAreaSize) const;
303
304 RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
305 bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
306
307 bool fixedBackgroundPaintsInLocalCoordinates() const;
308
309 void clipBorderSidePolygon(GraphicsContext&, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
310 BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
311
312 void paintOneBorderSide(GraphicsContext&, const RenderStyle&, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
313 const LayoutRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge[],
314 const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = nullptr);
315 void paintTranslucentBorderSides(GraphicsContext&, const RenderStyle&, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
316 const BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
317 void paintBorderSides(GraphicsContext&, const RenderStyle&, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
318 const IntPoint& innerBorderAdjustment, const BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
319 bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = nullptr);
320 void drawBoxSideFromPath(GraphicsContext&, const LayoutRect&, const Path&, const BorderEdge[],
321 float thickness, float drawThickness, BoxSide, const RenderStyle&,
322 Color, BorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
323 void paintMaskForTextFillBox(ImageBuffer*, const IntRect&, InlineFlowBox*, const LayoutRect&);
324};
325
326} // namespace WebCore
327
328SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderBoxModelObject, isBoxModelObject())
329