Michael Goderbauer 08961f8ec5 Format all c-like sources with clang-format (#4088)
* format

* license script adaptions

* updated licenses

* review comments
2017-09-12 15:36:20 -07:00

1010 lines
37 KiB
C++

/*
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc.
* All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef SKY_ENGINE_CORE_RENDERING_RENDEROBJECT_H_
#define SKY_ENGINE_CORE_RENDERING_RENDEROBJECT_H_
#include "flutter/sky/engine/core/editing/PositionWithAffinity.h"
#include "flutter/sky/engine/core/rendering/HitTestRequest.h"
#include "flutter/sky/engine/core/rendering/RenderObjectChildList.h"
#include "flutter/sky/engine/core/rendering/SubtreeLayoutScope.h"
#include "flutter/sky/engine/core/rendering/style/RenderStyle.h"
#include "flutter/sky/engine/core/rendering/style/StyleInheritedData.h"
#include "flutter/sky/engine/platform/geometry/FloatQuad.h"
#include "flutter/sky/engine/platform/geometry/LayoutRect.h"
#include "flutter/sky/engine/platform/transforms/TransformationMatrix.h"
namespace blink {
class AffineTransform;
class HitTestLocation;
class HitTestResult;
class InlineBox;
class InlineFlowBox;
class Position;
class RenderBlock;
class RenderBox;
class RenderBoxModelObject;
class RenderGeometryMap;
class RenderLayer;
class RenderView;
class TransformState;
struct PaintInfo;
// Sides used when drawing borders and outlines. The values should run clockwise
// from top.
enum BoxSide { BSTop, BSRight, BSBottom, BSLeft };
enum MarkingBehavior {
MarkOnlyThis,
MarkContainingBlockChain,
};
enum MapCoordinatesMode {
UseTransforms = 1 << 0,
// FIXME(sky): What is this for? Do we need it?
ApplyContainerFlip = 1 << 1,
// FIXME(sky): Remove
TraverseDocumentBoundaries = 1 << 2,
};
typedef unsigned MapCoordinatesFlags;
const int caretWidth = 1;
struct AnnotatedRegionValue {
bool operator==(const AnnotatedRegionValue& o) const {
return draggable == o.draggable && bounds == o.bounds;
}
LayoutRect bounds;
bool draggable;
};
typedef WTF::HashMap<const RenderLayer*, Vector<LayoutRect>> LayerHitTestRects;
#ifndef NDEBUG
const int showTreeCharacterOffset = 39;
#endif
// Base class for all rendering tree objects.
class RenderObject {
friend class RenderBlock;
friend class RenderObjectChildList;
WTF_MAKE_NONCOPYABLE(RenderObject);
public:
// TODO(ojan): Pass in a reference since the node can no longer be null.
explicit RenderObject();
virtual ~RenderObject();
virtual const char* renderName() const = 0;
String debugName() const;
RenderObject* parent() const { return m_parent; }
bool isDescendantOf(const RenderObject*) const;
RenderObject* previousSibling() const { return m_previous; }
RenderObject* nextSibling() const { return m_next; }
RenderObject* slowFirstChild() const {
if (const RenderObjectChildList* children = virtualChildren())
return children->firstChild();
return 0;
}
RenderObject* slowLastChild() const {
if (const RenderObjectChildList* children = virtualChildren())
return children->lastChild();
return 0;
}
virtual RenderObjectChildList* virtualChildren() { return 0; }
virtual const RenderObjectChildList* virtualChildren() const { return 0; }
RenderObject* nextInPreOrder() const;
RenderObject* nextInPreOrder(const RenderObject* stayWithin) const;
RenderObject* nextInPreOrderAfterChildren() const;
RenderObject* nextInPreOrderAfterChildren(
const RenderObject* stayWithin) const;
RenderObject* previousInPreOrder() const;
RenderObject* previousInPreOrder(const RenderObject* stayWithin) const;
RenderObject* childAt(unsigned) const;
RenderObject* lastLeafChild() const;
// The following six functions are used when the render tree hierarchy changes
// to make sure layers get properly added and removed. Since containership
// can be implemented by any subclass, and since a hierarchy can contain a
// mixture of boxes and other object types, these functions need to be in the
// base class.
RenderLayer* enclosingLayer() const;
void addLayers(RenderLayer* parentLayer);
void removeLayers(RenderLayer* parentLayer);
void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
RenderLayer* findNextLayer(RenderLayer* parentLayer,
RenderObject* startPoint,
bool checkParent = true);
// Convenience function for getting to the nearest enclosing box of a
// RenderObject.
RenderBox* enclosingBox() const;
RenderBoxModelObject* enclosingBoxModelObject() const;
#if ENABLE(ASSERT)
// Helper class forbidding calls to setNeedsLayout() during its lifetime.
class SetLayoutNeededForbiddenScope {
public:
explicit SetLayoutNeededForbiddenScope(RenderObject&);
~SetLayoutNeededForbiddenScope();
private:
RenderObject& m_renderObject;
bool m_preexistingForbidden;
};
void assertRendererLaidOut() const {
#ifndef NDEBUG
if (needsLayout())
showRenderTreeForThis();
#endif
ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
}
void assertSubtreeIsLaidOut() const {
for (const RenderObject* renderer = this; renderer;
renderer = renderer->nextInPreOrder())
renderer->assertRendererLaidOut();
}
#endif
bool skipInvalidationWhenLaidOutChildren() const;
// FIXME: This could be used when changing the size of a renderer without
// children to skip some invalidations.
bool rendererHasNoBoxEffect() const {
return !style()->hasVisualOverflowingEffect() && !style()->hasBorder() &&
!style()->hasBackground();
}
// Obtains the nearest enclosing block (including this block) that contributes
// a first-line style to our inline children.
virtual RenderBlock* firstLineBlock() const;
// RenderObject tree manipulation
//////////////////////////////////////////
virtual bool canHaveChildren() const { return virtualChildren(); }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const {
return true;
}
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*);
//////////////////////////////////////////
protected:
//////////////////////////////////////////
// Helper functions. Dangerous to use!
void setPreviousSibling(RenderObject* previous) { m_previous = previous; }
void setNextSibling(RenderObject* next) { m_next = next; }
void setParent(RenderObject* parent) { m_parent = parent; }
//////////////////////////////////////////
private:
#if ENABLE(ASSERT)
bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; }
void setNeedsLayoutIsForbidden(bool flag) {
m_setNeedsLayoutForbidden = flag;
}
#endif
void addAbsoluteRectForLayer(LayoutRect& result);
public:
#ifndef NDEBUG
void showTreeForThis() const;
void showRenderTreeForThis() const;
void showLineTreeForThis() const;
void showRenderObject() const;
// We don't make printedCharacters an optional parameter so that
// showRenderObject can be called from gdb easily.
void showRenderObject(int printedCharacters) const;
void showRenderTreeAndMark(const RenderObject* markedObject1 = 0,
const char* markedLabel1 = 0,
const RenderObject* markedObject2 = 0,
const char* markedLabel2 = 0,
int depth = 0) const;
#endif
static unsigned instanceCount() { return s_instanceCount; }
#if !ENABLE(OILPAN)
// RenderObjects are allocated out of the rendering partition.
void* operator new(size_t);
void operator delete(void*);
#endif
public:
virtual bool isBoxModelObject() const { return false; }
virtual bool isCanvas() const { return false; }
virtual bool isImage() const { return false; }
virtual bool isInlineBlock() const { return false; }
virtual bool isRenderBlock() const { return false; }
virtual bool isRenderParagraph() const { return false; }
virtual bool isRenderInline() const { return false; }
virtual bool isRenderView() const { return false; }
bool everHadLayout() const { return m_bitfields.everHadLayout(); }
bool alwaysCreateLineBoxesForRenderInline() const {
ASSERT(isRenderInline());
return m_bitfields.alwaysCreateLineBoxesForRenderInline();
}
void setAlwaysCreateLineBoxesForRenderInline(bool alwaysCreateLineBoxes) {
ASSERT(isRenderInline());
m_bitfields.setAlwaysCreateLineBoxesForRenderInline(alwaysCreateLineBoxes);
}
bool ancestorLineBoxDirty() const {
return m_bitfields.ancestorLineBoxDirty();
}
void setAncestorLineBoxDirty(bool value = true) {
m_bitfields.setAncestorLineBoxDirty(value);
if (value)
setNeedsLayout();
}
// SVG uses FloatPoint precise hit testing, and passes the point in parent
// coordinates instead of in paint invalidaiton container coordinates.
// Eventually the rest of the rendering tree will move to a similar model.
virtual bool nodeAtFloatPoint(const HitTestRequest&,
HitTestResult&,
const FloatPoint& pointInParent);
bool canHaveWhitespaceChildren() const { return !isFlexibleBox(); }
bool isOutOfFlowPositioned() const {
return m_bitfields.isOutOfFlowPositioned();
} // absolute or fixed positioning
bool isPositioned() const { return m_bitfields.isPositioned(); }
bool isText() const { return m_bitfields.isText(); }
bool isBox() const { return m_bitfields.isBox(); }
bool isInline() const { return m_bitfields.isInline(); } // inline object
bool isDragging() const { return m_bitfields.isDragging(); }
bool isReplaced() const {
return m_bitfields.isReplaced();
} // a "replaced" element (see CSS)
bool hasLayer() const { return m_bitfields.hasLayer(); }
bool hasBoxDecorationBackground() const {
return m_bitfields.hasBoxDecorationBackground();
}
bool hasBackground() const { return style()->hasBackground(); }
bool hasEntirelyFixedBackground() const;
bool needsLayoutBecauseOfChildren() const {
return needsLayout() && !selfNeedsLayout() &&
!needsPositionedMovementLayout() &&
!needsSimplifiedNormalFlowLayout();
}
bool needsLayout() const {
return m_bitfields.selfNeedsLayout() ||
m_bitfields.normalChildNeedsLayout() ||
m_bitfields.posChildNeedsLayout() ||
m_bitfields.needsSimplifiedNormalFlowLayout() ||
m_bitfields.needsPositionedMovementLayout();
}
bool selfNeedsLayout() const { return m_bitfields.selfNeedsLayout(); }
bool needsPositionedMovementLayout() const {
return m_bitfields.needsPositionedMovementLayout();
}
bool needsPositionedMovementLayoutOnly() const {
return m_bitfields.needsPositionedMovementLayout() &&
!m_bitfields.selfNeedsLayout() &&
!m_bitfields.normalChildNeedsLayout() &&
!m_bitfields.posChildNeedsLayout() &&
!m_bitfields.needsSimplifiedNormalFlowLayout();
}
bool posChildNeedsLayout() const { return m_bitfields.posChildNeedsLayout(); }
bool needsSimplifiedNormalFlowLayout() const {
return m_bitfields.needsSimplifiedNormalFlowLayout();
}
bool normalChildNeedsLayout() const {
return m_bitfields.normalChildNeedsLayout();
}
bool preferredLogicalWidthsDirty() const {
return m_bitfields.preferredLogicalWidthsDirty();
}
bool needsOverflowRecalcAfterStyleChange() const {
return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange() ||
m_bitfields.childNeedsOverflowRecalcAfterStyleChange();
}
bool selfNeedsOverflowRecalcAfterStyleChange() const {
return m_bitfields.selfNeedsOverflowRecalcAfterStyleChange();
}
bool childNeedsOverflowRecalcAfterStyleChange() const {
return m_bitfields.childNeedsOverflowRecalcAfterStyleChange();
}
bool isSelectionBorder() const;
bool hasClip() const {
return isOutOfFlowPositioned() && !style()->hasAutoClip();
}
bool hasOverflowClip() const { return m_bitfields.hasOverflowClip(); }
bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); }
bool hasTransform() const { return m_bitfields.hasTransform(); }
bool hasClipPath() const { return style() && style()->clipPath(); }
inline bool preservesNewline() const;
bool isRooted() const;
// Returns the object containing this one. Can be different from parent for
// positioned elements. If paintInvalidationContainer and
// paintInvalidationContainerSkipped are not null, on return
// *paintInvalidationContainerSkipped is true if the renderer returned is an
// ancestor of paintInvalidationContainer.
RenderObject* container(const RenderBox* paintInvalidationContainer = 0,
bool* paintInvalidationContainerSkipped = 0) const;
void markContainingBlocksForLayout(bool scheduleRelayout = true,
RenderObject* newRoot = 0,
SubtreeLayoutScope* = 0);
void setNeedsLayout(MarkingBehavior = MarkContainingBlockChain,
SubtreeLayoutScope* = 0);
void clearNeedsLayout();
void setChildNeedsLayout(MarkingBehavior = MarkContainingBlockChain,
SubtreeLayoutScope* = 0);
void setNeedsPositionedMovementLayout();
void setPreferredLogicalWidthsDirty(
MarkingBehavior = MarkContainingBlockChain);
void clearPreferredLogicalWidthsDirty();
void invalidateContainerPreferredLogicalWidths();
void setNeedsLayoutAndPrefWidthsRecalc() {
setNeedsLayout();
setPreferredLogicalWidthsDirty();
}
void setPositionState(EPosition position) {
ASSERT(position != AbsolutePosition || isBox());
m_bitfields.setPositionedState(position);
}
void clearPositionedState() { m_bitfields.clearPositionedState(); }
void setInline(bool isInline) { m_bitfields.setIsInline(isInline); }
void setIsText() { m_bitfields.setIsText(true); }
void setIsBox() { m_bitfields.setIsBox(true); }
void setReplaced(bool isReplaced) { m_bitfields.setIsReplaced(isReplaced); }
void setHasOverflowClip(bool hasOverflowClip) {
m_bitfields.setHasOverflowClip(hasOverflowClip);
}
void setHasLayer(bool hasLayer) { m_bitfields.setHasLayer(hasLayer); }
void setHasTransform(bool hasTransform) {
m_bitfields.setHasTransform(hasTransform);
}
void setHasBoxDecorationBackground(bool b) {
m_bitfields.setHasBoxDecorationBackground(b);
}
void scheduleRelayout();
void updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers);
void updateImage(StyleImage*, StyleImage*);
// paintOffset is the offset from the origin of the GraphicsContext at which
// to paint the current object.
virtual void paint(PaintInfo&,
const LayoutPoint& paintOffset,
Vector<RenderBox*>& layers);
// Subclasses must reimplement this method to compute the size and position
// of this object and all its descendants.
virtual void layout() = 0;
/* This function performs a layout only if one is needed. */
void layoutIfNeeded() {
if (needsLayout())
layout();
}
void forceLayout();
void forceChildLayout();
bool hitTest(const HitTestRequest&,
HitTestResult&,
const HitTestLocation& locationInContainer,
const LayoutPoint& accumulatedOffset);
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
virtual bool nodeAtPoint(const HitTestRequest&,
HitTestResult&,
const HitTestLocation& locationInContainer,
const LayoutPoint& accumulatedOffset);
virtual PositionWithAffinity positionForPoint(const LayoutPoint&);
PositionWithAffinity createPositionWithAffinity(int offset, EAffinity);
PositionWithAffinity createPositionWithAffinity(const Position&);
virtual void dirtyLinesFromChangedChild(RenderObject*);
// Set the style of the object and update the state of the object accordingly.
void setStyle(PassRefPtr<RenderStyle>);
// Updates only the local style ptr of the object. Does not update the state
// of the object, and so only should be called when the style is known not to
// have changed (or from setStyle).
void setStyleInternal(PassRefPtr<RenderStyle> style) { m_style = style; }
// returns the containing block level element for this element.
RenderBlock* containingBlock() const;
// Convert the given local point to absolute coordinates
// FIXME: Temporary. If UseTransforms is true, take transforms into account.
// Eventually localToAbsolute() will always be transform-aware.
FloatPoint localToAbsolute(const FloatPoint& localPoint = FloatPoint(),
MapCoordinatesFlags = 0) const;
FloatPoint absoluteToLocal(const FloatPoint&, MapCoordinatesFlags = 0) const;
// Convert a local quad to absolute coordinates, taking transforms into
// account.
FloatQuad localToAbsoluteQuad(const FloatQuad& quad,
MapCoordinatesFlags mode = 0) const {
return localToContainerQuad(quad, 0, mode);
}
// Convert an absolute quad to local coordinates.
FloatQuad absoluteToLocalQuad(const FloatQuad&,
MapCoordinatesFlags mode = 0) const;
// Convert a local quad into the coordinate system of container, taking
// transforms into account.
FloatQuad localToContainerQuad(const FloatQuad&,
const RenderBox* paintInvalidatinoContainer,
MapCoordinatesFlags = 0) const;
FloatPoint localToContainerPoint(const FloatPoint&,
const RenderBox* paintInvalidationContainer,
MapCoordinatesFlags = 0) const;
// Return the offset from the container() renderer (excluding transforms). In
// multi-column layout, different offsets apply at different points, so return
// the offset that applies to the given point.
virtual LayoutSize offsetFromContainer(const RenderObject*,
const LayoutPoint&,
bool* offsetDependsOnPoint = 0) const;
// Return the offset from an object up the container() chain. Asserts that
// none of the intermediate objects have transforms.
LayoutSize offsetFromAncestorContainer(const RenderObject*) const;
IntRect absoluteBoundingBoxRect() const;
// Build an array of quads in absolute coords for line boxes
virtual void absoluteQuads(Vector<FloatQuad>&) const {}
virtual LayoutUnit minPreferredLogicalWidth() const { return 0; }
virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; }
RenderStyle* style() const { return m_style.get(); }
/* The two following methods are inlined in RenderObjectInlines.h */
RenderStyle* firstLineStyle() const;
RenderStyle* style(bool firstLine) const;
struct AppliedTextDecoration {
Color color;
TextDecorationStyle style;
AppliedTextDecoration()
: color(Color::transparent), style(TextDecorationStyleSolid) {}
};
void getTextDecorations(unsigned decorations,
AppliedTextDecoration& underline,
AppliedTextDecoration& overline,
AppliedTextDecoration& linethrough,
bool quirksMode = false,
bool firstlineStyle = false);
// Overriden by RenderText for character length, used in line layout code.
virtual unsigned length() const { return 1; }
// FIXME(sky): Remove
bool isFloatingOrOutOfFlowPositioned() const {
return isOutOfFlowPositioned();
}
bool isTransparent() const { return style()->hasOpacity(); }
float opacity() const { return style()->opacity(); }
enum SelectionState {
SelectionNone, // The object is not selected.
SelectionStart, // The object either contains the start of a selection run
// or is the start of a run
SelectionInside, // The object is fully encompassed by a selection run
SelectionEnd, // The object either contains the end of a selection run or
// is the end of a run
SelectionBoth // The object contains an entire run or is the sole selected
// object in that run
};
// The current selection state for an object. For blocks, the state refers to
// the state of the leaf descendants (as described above in the SelectionState
// enum declaration).
SelectionState selectionState() const { return m_bitfields.selectionState(); }
virtual void setSelectionState(SelectionState state) {
m_bitfields.setSelectionState(state);
}
inline void setSelectionStateIfNeeded(SelectionState);
bool canUpdateSelectionOnRootLineBoxes();
virtual bool canBeSelectionLeaf() const { return false; }
bool hasSelectedChildren() const { return selectionState() != SelectionNone; }
bool isSelectable() const;
// Obtains the selection colors that should be used when painting a selection.
Color selectionBackgroundColor() const;
Color selectionForegroundColor() const;
Color selectionEmphasisMarkColor() const;
// Whether or not a given block needs to paint selection gaps.
virtual bool shouldPaintSelectionGaps() const { return false; }
/**
* Returns the local coordinates of the caret within this render object.
* @param caretOffset zero-based offset determining position within the render
* object.
* @param extraWidthToEndOfLine optional out arg to give extra width to end of
* line - useful for character range rect computations
*/
virtual LayoutRect localCaretRect(InlineBox*,
int caretOffset,
LayoutUnit* extraWidthToEndOfLine = 0);
// When performing a global document tear-down, the renderer of the document
// is cleared. We use this as a hook to detect the case of document
// destruction and don't waste time doing unnecessary work.
bool documentBeingDestroyed() const;
virtual void destroy();
// Virtual function helper for the new FlexibleBox Layout (display:
// -webkit-flex).
virtual bool isFlexibleBox() const { return false; }
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
virtual int previousOffset(int current) const;
virtual int previousOffsetForBackwardDeletion(int current) const;
virtual int nextOffset(int current) const;
void selectionStartEnd(int& spos, int& epos) const;
void remove() {
if (parent())
parent()->removeChild(this);
}
bool supportsTouchAction() const;
bool visibleToHitTestRequest(const HitTestRequest& request) const {
return (request.ignorePointerEventsNone() ||
style()->pointerEvents() != PE_NONE);
}
bool visibleToHitTesting() const {
return style()->pointerEvents() != PE_NONE;
}
// Map points and quads through elements, potentially via 3d transforms. You
// should never need to call these directly; use
// localToAbsolute/absoluteToLocal methods instead.
virtual void mapLocalToContainer(
const RenderBox* paintInvalidationContainer,
TransformState&,
MapCoordinatesFlags = ApplyContainerFlip) const;
virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags,
TransformState&) const;
// Pushes state onto RenderGeometryMap about how to map coordinates from this
// renderer to its container, or ancestorToStopAt (whichever is encountered
// first). Returns the renderer which was mapped to (container or
// ancestorToStopAt).
virtual const RenderObject* pushMappingToContainer(
const RenderBox* ancestorToStopAt,
RenderGeometryMap&) const;
bool shouldUseTransformFromContainer(const RenderObject* container) const;
void getTransformFromContainer(const RenderObject* container,
const LayoutSize& offsetInContainer,
TransformationMatrix&) const;
bool createsGroup() const { return isTransparent(); }
virtual void addFocusRingRects(
Vector<IntRect>&,
const LayoutPoint& /* additionalOffset */,
const RenderBox* /* paintContainer */ = 0) const {};
RespectImageOrientationEnum shouldRespectImageOrientation() const;
bool onlyNeededPositionedMovementLayout() const {
return m_bitfields.onlyNeededPositionedMovementLayout();
}
void setOnlyNeededPositionedMovementLayout(bool b) {
m_bitfields.setOnlyNeededPositionedMovementLayout(b);
}
bool neededLayoutBecauseOfChildren() const {
return m_bitfields.neededLayoutBecauseOfChildren();
}
void setNeededLayoutBecauseOfChildren(bool b) {
m_bitfields.setNeededLayoutBecauseOfChildren(b);
}
void setNeedsOverflowRecalcAfterStyleChange();
void markContainingBlocksForOverflowRecalc();
protected:
// Overrides should call the superclass at the end. m_style will be 0 the
// first time this function will be called.
virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle);
// Overrides should call the superclass at the start. |oldStyle| will be 0 the
// first time this function is called.
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
void drawLineForBoxSide(GraphicsContext*,
int x1,
int y1,
int x2,
int y2,
BoxSide,
Color,
EBorderStyle,
int adjbw1,
int adjbw2,
bool antialias = false);
void drawDashedOrDottedBoxSide(GraphicsContext*,
int x1,
int y1,
int x2,
int y2,
BoxSide,
Color,
int thickness,
EBorderStyle,
bool antialias);
void drawDoubleBoxSide(GraphicsContext*,
int x1,
int y1,
int x2,
int y2,
int length,
BoxSide,
Color,
int thickness,
int adjacentWidth1,
int adjacentWidth2,
bool antialias);
void drawRidgeOrGrooveBoxSide(GraphicsContext*,
int x1,
int y1,
int x2,
int y2,
BoxSide,
Color,
EBorderStyle,
int adjacentWidth1,
int adjacentWidth2,
bool antialias);
void drawSolidBoxSide(GraphicsContext*,
int x1,
int y1,
int x2,
int y2,
BoxSide,
Color,
int adjacentWidth1,
int adjacentWidth2,
bool antialias);
void addChildFocusRingRects(Vector<IntRect>&,
const LayoutPoint& additionalOffset,
const RenderBox* paintContainer) const;
void clearLayoutRootIfNeeded() const;
virtual void willBeDestroyed();
void postDestroy();
void insertedIntoTree();
void willBeRemovedFromTree();
private:
bool hasImmediateNonWhitespaceTextChildOrPropertiesDependentOnColor() const;
StyleDifference adjustStyleDifference(StyleDifference) const;
Color selectionColor() const;
#if ENABLE(ASSERT)
void checkBlockPositionedObjectsNeedLayout();
#endif
// FIXME(sky): This method is just to avoid copy-paste.
// Merge container into containingBlock and then get rid of this method.
bool canContainAbsolutePositionObjects() const {
return isRenderView() || (hasTransform() && isRenderBlock());
}
RefPtr<RenderStyle> m_style;
RawPtr<RenderObject> m_parent;
RawPtr<RenderObject> m_previous;
RawPtr<RenderObject> m_next;
#if ENABLE(ASSERT)
unsigned m_setNeedsLayoutForbidden : 1;
#if ENABLE(OILPAN)
protected:
unsigned m_didCallDestroy : 1;
private:
#endif
#endif
#define ADD_BOOLEAN_BITFIELD(name, Name) \
private: \
unsigned m_##name : 1; \
\
public: \
bool name() const { return m_##name; } \
void set##Name(bool name) { m_##name = name; }
class RenderObjectBitfields {
// FIXME(sky): Remove this enum and just use EPosition directly.
enum PositionedState {
IsStaticallyPositioned = 0,
IsOutOfFlowPositioned = 1,
};
public:
RenderObjectBitfields()
: m_selfNeedsLayout(false),
m_onlyNeededPositionedMovementLayout(false),
m_neededLayoutBecauseOfChildren(false),
m_needsPositionedMovementLayout(false),
m_normalChildNeedsLayout(false),
m_posChildNeedsLayout(false),
m_needsSimplifiedNormalFlowLayout(false),
m_preferredLogicalWidthsDirty(false),
m_selfNeedsOverflowRecalcAfterStyleChange(false),
m_childNeedsOverflowRecalcAfterStyleChange(false),
m_isText(false),
m_isBox(false),
m_isInline(true),
m_isReplaced(false),
m_isDragging(false),
m_hasLayer(false),
m_hasOverflowClip(false),
m_hasTransform(false),
m_hasBoxDecorationBackground(false),
m_everHadLayout(false),
m_ancestorLineBoxDirty(false),
m_alwaysCreateLineBoxesForRenderInline(false),
m_positionedState(IsStaticallyPositioned),
m_selectionState(SelectionNone) {}
// 32 bits have been used in the first word, and 11 in the second.
ADD_BOOLEAN_BITFIELD(selfNeedsLayout, SelfNeedsLayout);
ADD_BOOLEAN_BITFIELD(onlyNeededPositionedMovementLayout,
OnlyNeededPositionedMovementLayout);
ADD_BOOLEAN_BITFIELD(neededLayoutBecauseOfChildren,
NeededLayoutBecauseOfChildren);
ADD_BOOLEAN_BITFIELD(needsPositionedMovementLayout,
NeedsPositionedMovementLayout);
ADD_BOOLEAN_BITFIELD(normalChildNeedsLayout, NormalChildNeedsLayout);
ADD_BOOLEAN_BITFIELD(posChildNeedsLayout, PosChildNeedsLayout);
ADD_BOOLEAN_BITFIELD(needsSimplifiedNormalFlowLayout,
NeedsSimplifiedNormalFlowLayout);
ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty,
PreferredLogicalWidthsDirty);
ADD_BOOLEAN_BITFIELD(selfNeedsOverflowRecalcAfterStyleChange,
SelfNeedsOverflowRecalcAfterStyleChange);
ADD_BOOLEAN_BITFIELD(childNeedsOverflowRecalcAfterStyleChange,
ChildNeedsOverflowRecalcAfterStyleChange);
ADD_BOOLEAN_BITFIELD(isText, IsText);
ADD_BOOLEAN_BITFIELD(isBox, IsBox);
ADD_BOOLEAN_BITFIELD(isInline, IsInline);
ADD_BOOLEAN_BITFIELD(isReplaced, IsReplaced);
ADD_BOOLEAN_BITFIELD(isDragging, IsDragging);
ADD_BOOLEAN_BITFIELD(hasLayer, HasLayer);
ADD_BOOLEAN_BITFIELD(
hasOverflowClip,
HasOverflowClip); // Set in the case of overflow:auto/scroll/hidden
ADD_BOOLEAN_BITFIELD(hasTransform, HasTransform);
ADD_BOOLEAN_BITFIELD(hasBoxDecorationBackground,
HasBoxDecorationBackground);
ADD_BOOLEAN_BITFIELD(everHadLayout, EverHadLayout);
ADD_BOOLEAN_BITFIELD(ancestorLineBoxDirty, AncestorLineBoxDirty);
// from RenderInline
ADD_BOOLEAN_BITFIELD(alwaysCreateLineBoxesForRenderInline,
AlwaysCreateLineBoxesForRenderInline);
private:
unsigned m_positionedState : 1; // PositionedState
unsigned m_selectionState : 3; // SelectionState
public:
bool isOutOfFlowPositioned() const {
return m_positionedState == IsOutOfFlowPositioned;
}
bool isPositioned() const {
return m_positionedState != IsStaticallyPositioned;
}
void setPositionedState(int positionState) {
m_positionedState = static_cast<PositionedState>(positionState);
}
void clearPositionedState() { m_positionedState = StaticPosition; }
ALWAYS_INLINE SelectionState selectionState() const {
return static_cast<SelectionState>(m_selectionState);
}
ALWAYS_INLINE void setSelectionState(SelectionState selectionState) {
m_selectionState = selectionState;
}
};
#undef ADD_BOOLEAN_BITFIELD
RenderObjectBitfields m_bitfields;
void setSelfNeedsLayout(bool b) { m_bitfields.setSelfNeedsLayout(b); }
void setNeedsPositionedMovementLayout(bool b) {
m_bitfields.setNeedsPositionedMovementLayout(b);
}
void setNormalChildNeedsLayout(bool b) {
m_bitfields.setNormalChildNeedsLayout(b);
}
void setPosChildNeedsLayout(bool b) { m_bitfields.setPosChildNeedsLayout(b); }
void setNeedsSimplifiedNormalFlowLayout(bool b) {
m_bitfields.setNeedsSimplifiedNormalFlowLayout(b);
}
void setIsDragging(bool b) { m_bitfields.setIsDragging(b); }
void setEverHadLayout(bool b) { m_bitfields.setEverHadLayout(b); }
void setSelfNeedsOverflowRecalcAfterStyleChange(bool b) {
m_bitfields.setSelfNeedsOverflowRecalcAfterStyleChange(b);
}
void setChildNeedsOverflowRecalcAfterStyleChange(bool b) {
m_bitfields.setChildNeedsOverflowRecalcAfterStyleChange(b);
}
private:
// Store state between styleWillChange and styleDidChange
static bool s_affectsParentBlock;
static unsigned s_instanceCount;
};
// Allow equality comparisons of RenderObjects by reference or pointer,
// interchangeably.
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(RenderObject)
inline bool RenderObject::documentBeingDestroyed() const {
return false;
}
// setNeedsLayout() won't cause full paint invalidations as
// setNeedsLayout() does. Otherwise the two methods are identical.
inline void RenderObject::setNeedsLayout(MarkingBehavior markParents,
SubtreeLayoutScope* layouter) {
ASSERT(!isSetNeedsLayoutForbidden());
bool alreadyNeededLayout = m_bitfields.selfNeedsLayout();
setSelfNeedsLayout(true);
if (!alreadyNeededLayout) {
if (markParents == MarkContainingBlockChain &&
(!layouter || layouter->root() != this))
markContainingBlocksForLayout(true, 0, layouter);
}
}
inline void RenderObject::clearNeedsLayout() {
setOnlyNeededPositionedMovementLayout(needsPositionedMovementLayoutOnly());
setNeededLayoutBecauseOfChildren(needsLayoutBecauseOfChildren());
setSelfNeedsLayout(false);
setEverHadLayout(true);
setPosChildNeedsLayout(false);
setNeedsSimplifiedNormalFlowLayout(false);
setNormalChildNeedsLayout(false);
setNeedsPositionedMovementLayout(false);
setAncestorLineBoxDirty(false);
#if ENABLE(ASSERT)
checkBlockPositionedObjectsNeedLayout();
#endif
}
inline void RenderObject::setChildNeedsLayout(MarkingBehavior markParents,
SubtreeLayoutScope* layouter) {
ASSERT(!isSetNeedsLayoutForbidden());
bool alreadyNeededLayout = normalChildNeedsLayout();
setNormalChildNeedsLayout(true);
// FIXME: Replace MarkOnlyThis with the SubtreeLayoutScope code path and
// remove the MarkingBehavior argument entirely.
if (!alreadyNeededLayout && markParents == MarkContainingBlockChain &&
(!layouter || layouter->root() != this))
markContainingBlocksForLayout(true, 0, layouter);
}
inline void RenderObject::setNeedsPositionedMovementLayout() {
bool alreadyNeededLayout = needsPositionedMovementLayout();
setNeedsPositionedMovementLayout(true);
ASSERT(!isSetNeedsLayoutForbidden());
if (!alreadyNeededLayout)
markContainingBlocksForLayout();
}
inline bool RenderObject::preservesNewline() const {
return style()->preserveNewline();
}
inline void RenderObject::setSelectionStateIfNeeded(SelectionState state) {
if (selectionState() == state)
return;
setSelectionState(state);
}
#define DEFINE_RENDER_OBJECT_TYPE_CASTS(thisType, predicate) \
DEFINE_TYPE_CASTS(thisType, RenderObject, object, object->predicate, \
object.predicate)
} // namespace blink
#ifndef NDEBUG
// Outside the WebCore namespace for ease of invocation from gdb.
void showTree(const blink::RenderObject*);
void showLineTree(const blink::RenderObject*);
void showRenderTree(const blink::RenderObject* object1);
// We don't make object2 an optional parameter so that showRenderTree
// can be called from gdb easily.
void showRenderTree(const blink::RenderObject* object1,
const blink::RenderObject* object2);
#endif
#endif // SKY_ENGINE_CORE_RENDERING_RENDEROBJECT_H_