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#ifndef RenderBoxModelObject_h
25#define RenderBoxModelObject_h
26
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 ContentChangeType {
45    ImageChanged,
46    MaskImageChanged,
47    BackgroundImageChanged,
48    CanvasChanged,
49    CanvasPixelsChanged,
50    VideoChanged,
51    FullScreenChanged
52};
53
54class KeyframeList;
55class InlineFlowBox;
56class StickyPositionViewportConstraints;
57
58// This class is the base for all objects that adhere to the CSS box model as described
59// at http://www.w3.org/TR/CSS21/box.html
60
61class RenderBoxModelObject : public RenderLayerModelObject {
62public:
63    RenderBoxModelObject(ContainerNode*);
64    virtual ~RenderBoxModelObject();
65
66    LayoutSize relativePositionOffset() const;
67    LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
68
69    void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& viewportRect) const;
70    LayoutSize stickyPositionOffset() const;
71    LayoutSize stickyPositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
72
73    LayoutSize offsetForInFlowPosition() const;
74    LayoutSize paintOffset() const;
75
76    // IE extensions. Used to calculate offsetWidth/Height.  Overridden by inlines (RenderFlow)
77    // to return the remaining width on a given line (and the height of a single line).
78    virtual LayoutUnit offsetLeft() const;
79    virtual LayoutUnit offsetTop() const;
80    virtual LayoutUnit offsetWidth() const = 0;
81    virtual LayoutUnit offsetHeight() const = 0;
82
83    int pixelSnappedOffsetLeft() const { return roundToInt(offsetLeft()); }
84    int pixelSnappedOffsetTop() const { return roundToInt(offsetTop()); }
85    virtual int pixelSnappedOffsetWidth() const;
86    virtual int pixelSnappedOffsetHeight() const;
87
88    virtual void updateFromStyle() OVERRIDE;
89
90    virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns(); }
91
92    // This will work on inlines to return the bounding box of all of the lines' border boxes.
93    virtual IntRect borderBoundingBox() const = 0;
94
95    // These return the CSS computed padding values.
96    LayoutUnit computedCSSPaddingTop() const { return computedCSSPadding(style()->paddingTop()); }
97    LayoutUnit computedCSSPaddingBottom() const { return computedCSSPadding(style()->paddingBottom()); }
98    LayoutUnit computedCSSPaddingLeft() const { return computedCSSPadding(style()->paddingLeft()); }
99    LayoutUnit computedCSSPaddingRight() const { return computedCSSPadding(style()->paddingRight()); }
100    LayoutUnit computedCSSPaddingBefore() const { return computedCSSPadding(style()->paddingBefore()); }
101    LayoutUnit computedCSSPaddingAfter() const { return computedCSSPadding(style()->paddingAfter()); }
102    LayoutUnit computedCSSPaddingStart() const { return computedCSSPadding(style()->paddingStart()); }
103    LayoutUnit computedCSSPaddingEnd() const { return computedCSSPadding(style()->paddingEnd()); }
104
105    // These functions are used during layout. Table cells and the MathML
106    // code override them to include some extra intrinsic padding.
107    virtual LayoutUnit paddingTop() const { return computedCSSPaddingTop(); }
108    virtual LayoutUnit paddingBottom() const { return computedCSSPaddingBottom(); }
109    virtual LayoutUnit paddingLeft() const { return computedCSSPaddingLeft(); }
110    virtual LayoutUnit paddingRight() const { return computedCSSPaddingRight(); }
111    virtual LayoutUnit paddingBefore() const { return computedCSSPaddingBefore(); }
112    virtual LayoutUnit paddingAfter() const { return computedCSSPaddingAfter(); }
113    virtual LayoutUnit paddingStart() const { return computedCSSPaddingStart(); }
114    virtual LayoutUnit paddingEnd() const { return computedCSSPaddingEnd(); }
115
116    virtual int borderTop() const { return style()->borderTopWidth(); }
117    virtual int borderBottom() const { return style()->borderBottomWidth(); }
118    virtual int borderLeft() const { return style()->borderLeftWidth(); }
119    virtual int borderRight() const { return style()->borderRightWidth(); }
120    virtual int borderBefore() const { return style()->borderBeforeWidth(); }
121    virtual int borderAfter() const { return style()->borderAfterWidth(); }
122    virtual int borderStart() const { return style()->borderStartWidth(); }
123    virtual int borderEnd() const { return style()->borderEndWidth(); }
124
125    LayoutUnit borderAndPaddingStart() const { return borderStart() + paddingStart(); }
126    LayoutUnit borderAndPaddingBefore() const { return borderBefore() + paddingBefore(); }
127    LayoutUnit borderAndPaddingAfter() const { return borderAfter() + paddingAfter(); }
128
129    LayoutUnit borderAndPaddingHeight() const { return borderTop() + borderBottom() + paddingTop() + paddingBottom(); }
130    LayoutUnit borderAndPaddingWidth() const { return borderLeft() + borderRight() + paddingLeft() + paddingRight(); }
131    LayoutUnit borderAndPaddingLogicalHeight() const { return borderAndPaddingBefore() + borderAndPaddingAfter(); }
132    LayoutUnit borderAndPaddingLogicalWidth() const { return borderStart() + borderEnd() + paddingStart() + paddingEnd(); }
133    LayoutUnit borderAndPaddingLogicalLeft() const { return style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
134
135    LayoutUnit borderLogicalLeft() const { return style()->isHorizontalWritingMode() ? borderLeft() : borderTop(); }
136    LayoutUnit borderLogicalRight() const { return style()->isHorizontalWritingMode() ? borderRight() : borderBottom(); }
137
138    LayoutUnit paddingLogicalLeft() const { return style()->isHorizontalWritingMode() ? paddingLeft() : paddingTop(); }
139    LayoutUnit paddingLogicalRight() const { return style()->isHorizontalWritingMode() ? paddingRight() : paddingBottom(); }
140
141    virtual LayoutUnit marginTop() const = 0;
142    virtual LayoutUnit marginBottom() const = 0;
143    virtual LayoutUnit marginLeft() const = 0;
144    virtual LayoutUnit marginRight() const = 0;
145    virtual LayoutUnit marginBefore(const RenderStyle* otherStyle = 0) const = 0;
146    virtual LayoutUnit marginAfter(const RenderStyle* otherStyle = 0) const = 0;
147    virtual LayoutUnit marginStart(const RenderStyle* otherStyle = 0) const = 0;
148    virtual LayoutUnit marginEnd(const RenderStyle* otherStyle = 0) const = 0;
149    LayoutUnit marginHeight() const { return marginTop() + marginBottom(); }
150    LayoutUnit marginWidth() const { return marginLeft() + marginRight(); }
151    LayoutUnit marginLogicalHeight() const { return marginBefore() + marginAfter(); }
152    LayoutUnit marginLogicalWidth() const { return marginStart() + marginEnd(); }
153
154    bool hasInlineDirectionBordersPaddingOrMargin() const { return hasInlineDirectionBordersOrPadding() || marginStart()|| marginEnd(); }
155    bool hasInlineDirectionBordersOrPadding() const { return borderStart() || borderEnd() || paddingStart()|| paddingEnd(); }
156
157    virtual LayoutUnit containingBlockLogicalWidthForContent() const;
158
159    virtual void childBecameNonInline(RenderObject* /*child*/) { }
160
161    void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle*, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
162    bool paintNinePieceImage(GraphicsContext*, const LayoutRect&, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
163    void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
164    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
165
166    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox* = 0) const;
167
168    // Overridden by subclasses to determine line height and baseline position.
169    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
170    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
171
172    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
173
174    void highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*);
175
176    virtual void setSelectionState(SelectionState s);
177
178    bool canHaveBoxInfoInRegion() const { return !isFloating() && !isReplaced() && !isInline() && !hasColumns() && !isTableCell() && isBlockFlow(); }
179
180    void getGeometryForBackgroundImage(const RenderLayerModelObject* paintContainer, IntRect& destRect, IntPoint& phase, IntSize& tileSize) const;
181#if USE(ACCELERATED_COMPOSITING)
182    void contentChanged(ContentChangeType);
183    bool hasAcceleratedCompositing() const;
184
185    bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
186    void transitionPaused(double timeOffset, CSSPropertyID);
187    void transitionFinished(CSSPropertyID);
188
189    bool startAnimation(double timeOffset, const Animation*, const KeyframeList& keyframes);
190    void animationPaused(double timeOffset, const String& name);
191    void animationFinished(const String& name);
192
193    void suspendAnimations(double time = 0);
194#endif
195
196protected:
197    virtual void willBeDestroyed();
198
199    class BackgroundImageGeometry {
200    public:
201        BackgroundImageGeometry()
202            : m_hasNonLocalGeometry(false)
203        { }
204        IntPoint destOrigin() const { return m_destOrigin; }
205        void setDestOrigin(const IntPoint& destOrigin)
206        {
207            m_destOrigin = destOrigin;
208        }
209
210        IntRect destRect() const { return m_destRect; }
211        void setDestRect(const IntRect& destRect)
212        {
213            m_destRect = destRect;
214        }
215
216        // Returns the phase relative to the destination rectangle.
217        IntPoint relativePhase() const;
218
219        IntPoint phase() const { return m_phase; }
220        void setPhase(const IntPoint& phase)
221        {
222            m_phase = phase;
223        }
224
225        IntSize tileSize() const { return m_tileSize; }
226        void setTileSize(const IntSize& tileSize)
227        {
228            m_tileSize = tileSize;
229        }
230
231        void setPhaseX(int x) { m_phase.setX(x); }
232        void setPhaseY(int y) { m_phase.setY(y); }
233
234        void setNoRepeatX(int xOffset);
235        void setNoRepeatY(int yOffset);
236
237        void useFixedAttachment(const IntPoint& attachmentPoint);
238
239        void clip(const IntRect&);
240
241        void setHasNonLocalGeometry(bool hasNonLocalGeometry = true) { m_hasNonLocalGeometry = hasNonLocalGeometry; }
242        bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; }
243
244    private:
245        IntRect m_destRect;
246        IntPoint m_destOrigin;
247        IntPoint m_phase;
248        IntSize m_tileSize;
249        bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
250    };
251
252    LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const;
253
254    void calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0) const;
255    void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
256    bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
257    bool borderObscuresBackground() const;
258    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
259    LayoutRect borderInnerRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance) const;
260
261    bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
262
263    RenderBoxModelObject* continuation() const;
264    void setContinuation(RenderBoxModelObject*);
265
266    LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
267
268    static bool shouldAntialiasLines(GraphicsContext*);
269
270    static void clipRoundedInnerRect(GraphicsContext*, const LayoutRect&, const RoundedRect& clipRect);
271
272    bool hasAutoHeightOrContainingBlockWithAutoHeight() const;
273
274public:
275    // For RenderBlocks and RenderInlines with m_style->styleType() == FIRST_LETTER, this tracks their remaining text fragments
276    RenderObject* firstLetterRemainingText() const;
277    void setFirstLetterRemainingText(RenderObject*);
278
279    // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
280    // Since they are typically called only to move objects around within anonymous blocks (which only have layers in
281    // the case of column spans), the default for fullRemoveInsert is false rather than true.
282    void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
283    void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, bool fullRemoveInsert = false)
284    {
285        moveChildTo(toBoxModelObject, child, 0, fullRemoveInsert);
286    }
287    void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, bool fullRemoveInsert = false)
288    {
289        moveAllChildrenTo(toBoxModelObject, 0, fullRemoveInsert);
290    }
291    void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert = false)
292    {
293        moveChildrenTo(toBoxModelObject, firstChild(), 0, beforeChild, fullRemoveInsert);
294    }
295    // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the |endChild| to denote
296    // that all the kids from |startChild| onwards should be moved.
297    void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
298    {
299        moveChildrenTo(toBoxModelObject, startChild, endChild, 0, fullRemoveInsert);
300    }
301    void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
302
303private:
304    LayoutUnit computedCSSPadding(Length) const;
305    virtual bool isBoxModelObject() const { return true; }
306
307    virtual LayoutRect frameRectForStickyPositioning() const = 0;
308
309    IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const;
310
311    enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
312    IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
313
314    RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
315        bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
316
317    bool fixedBackgroundPaintsInLocalCoordinates() const;
318
319    void clipBorderSidePolygon(GraphicsContext*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
320                               BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
321    void clipBorderSideForComplexInnerPath(GraphicsContext*, const RoundedRect&, const RoundedRect&, BoxSide, const class BorderEdge[]);
322    void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
323                                const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[],
324                                const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
325    void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
326        const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
327    void paintBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
328        const IntPoint& innerBorderAdjustment, const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
329        bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
330    void drawBoxSideFromPath(GraphicsContext*, const LayoutRect&, const Path&, const class BorderEdge[],
331                            float thickness, float drawThickness, BoxSide, const RenderStyle*,
332                            Color, EBorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
333};
334
335inline RenderBoxModelObject* toRenderBoxModelObject(RenderObject* object)
336{
337    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBoxModelObject());
338    return static_cast<RenderBoxModelObject*>(object);
339}
340
341inline const RenderBoxModelObject* toRenderBoxModelObject(const RenderObject* object)
342{
343    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBoxModelObject());
344    return static_cast<const RenderBoxModelObject*>(object);
345}
346
347// This will catch anyone doing an unnecessary cast.
348void toRenderBoxModelObject(const RenderBoxModelObject*);
349
350} // namespace WebCore
351
352#endif // RenderBoxModelObject_h
353