| 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 | |