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 | |
30 | namespace WebCore { |
31 | |
32 | // Modes for some of the line-related functions. |
33 | enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes }; |
34 | enum LineDirectionMode { HorizontalLine, VerticalLine }; |
35 | typedef unsigned BorderEdgeFlags; |
36 | |
37 | enum BackgroundBleedAvoidance { |
38 | BackgroundBleedNone, |
39 | BackgroundBleedShrinkBackground, |
40 | BackgroundBleedUseTransparencyLayer, |
41 | BackgroundBleedBackgroundOverBorder |
42 | }; |
43 | |
44 | enum BaseBackgroundColorUsage { |
45 | BaseBackgroundColorUse, |
46 | BaseBackgroundColorOnly, |
47 | BaseBackgroundColorSkip |
48 | }; |
49 | |
50 | enum ContentChangeType { |
51 | ImageChanged, |
52 | MaskImageChanged, |
53 | BackgroundImageChanged, |
54 | CanvasChanged, |
55 | CanvasPixelsChanged, |
56 | VideoChanged, |
57 | FullScreenChanged |
58 | }; |
59 | |
60 | class BorderEdge; |
61 | class ImageBuffer; |
62 | class InlineFlowBox; |
63 | class RenderTextFragment; |
64 | class StickyPositionViewportConstraints; |
65 | |
66 | class BackgroundImageGeometry { |
67 | public: |
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 | |
93 | private: |
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 | |
105 | class RenderBoxModelObject : public RenderLayerModelObject { |
106 | WTF_MAKE_ISO_ALLOCATED(RenderBoxModelObject); |
107 | public: |
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 style().borderTopWidth(); } |
156 | virtual LayoutUnit borderBottom() const { return style().borderBottomWidth(); } |
157 | virtual LayoutUnit borderLeft() const { return style().borderLeftWidth(); } |
158 | virtual LayoutUnit borderRight() const { return style().borderRightWidth(); } |
159 | virtual LayoutUnit horizontalBorderExtent() const { return borderLeft() + borderRight(); } |
160 | virtual LayoutUnit verticalBorderExtent() const { return borderTop() + borderBottom(); } |
161 | virtual LayoutUnit borderBefore() const { return style().borderBeforeWidth(); } |
162 | virtual LayoutUnit borderAfter() const { return style().borderAfterWidth(); } |
163 | virtual LayoutUnit borderStart() const { return style().borderStartWidth(); } |
164 | virtual LayoutUnit borderEnd() const { return 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 | |
240 | protected: |
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 | |
268 | public: |
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 | |
294 | protected: |
295 | LayoutUnit computedCSSPadding(const Length&) const; |
296 | |
297 | private: |
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 | |
328 | SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderBoxModelObject, isBoxModelObject()) |
329 | |