| 1 | /* |
| 2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. |
| 3 | * |
| 4 | * This library is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Library General Public |
| 6 | * License as published by the Free Software Foundation; either |
| 7 | * version 2 of the License, or (at your option) any later version. |
| 8 | * |
| 9 | * This library is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Library General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Library General Public License |
| 15 | * along with this library; see the file COPYING.LIB. If not, write to |
| 16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 17 | * Boston, MA 02110-1301, USA. |
| 18 | * |
| 19 | */ |
| 20 | |
| 21 | #pragma once |
| 22 | |
| 23 | #include "RenderBoxModelObject.h" |
| 24 | #include "RenderText.h" |
| 25 | #include "TextFlags.h" |
| 26 | #include <wtf/IsoMalloc.h> |
| 27 | #include <wtf/TypeCasts.h> |
| 28 | |
| 29 | namespace WebCore { |
| 30 | |
| 31 | class HitTestRequest; |
| 32 | class HitTestResult; |
| 33 | class RootInlineBox; |
| 34 | |
| 35 | // InlineBox represents a rectangle that occurs on a line. It corresponds to |
| 36 | // some RenderObject (i.e., it represents a portion of that RenderObject). |
| 37 | class InlineBox { |
| 38 | WTF_MAKE_ISO_ALLOCATED(InlineBox); |
| 39 | public: |
| 40 | virtual ~InlineBox(); |
| 41 | |
| 42 | void assertNotDeleted() const; |
| 43 | |
| 44 | virtual void deleteLine() = 0; |
| 45 | virtual void () = 0; |
| 46 | virtual void attachLine() = 0; |
| 47 | |
| 48 | virtual bool isLineBreak() const { return renderer().isLineBreak(); } |
| 49 | |
| 50 | WEBCORE_EXPORT virtual void adjustPosition(float dx, float dy); |
| 51 | void adjustLogicalPosition(float deltaLogicalLeft, float deltaLogicalTop) |
| 52 | { |
| 53 | if (isHorizontal()) |
| 54 | adjustPosition(deltaLogicalLeft, deltaLogicalTop); |
| 55 | else |
| 56 | adjustPosition(deltaLogicalTop, deltaLogicalLeft); |
| 57 | } |
| 58 | void adjustLineDirectionPosition(float delta) |
| 59 | { |
| 60 | if (isHorizontal()) |
| 61 | adjustPosition(delta, 0); |
| 62 | else |
| 63 | adjustPosition(0, delta); |
| 64 | } |
| 65 | void adjustBlockDirectionPosition(float delta) |
| 66 | { |
| 67 | if (isHorizontal()) |
| 68 | adjustPosition(0, delta); |
| 69 | else |
| 70 | adjustPosition(delta, 0); |
| 71 | } |
| 72 | |
| 73 | virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) = 0; |
| 74 | virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) = 0; |
| 75 | |
| 76 | #if ENABLE(TREE_DEBUGGING) |
| 77 | void showNodeTreeForThis() const; |
| 78 | void showLineTreeForThis() const; |
| 79 | |
| 80 | virtual void outputLineTreeAndMark(WTF::TextStream&, const InlineBox* markedBox, int depth) const; |
| 81 | virtual void outputLineBox(WTF::TextStream&, bool mark, int depth) const; |
| 82 | virtual const char* boxName() const; |
| 83 | #endif |
| 84 | |
| 85 | bool behavesLikeText() const { return m_bitfields.behavesLikeText(); } |
| 86 | void setBehavesLikeText(bool behavesLikeText) { m_bitfields.setBehavesLikeText(behavesLikeText); } |
| 87 | |
| 88 | virtual bool isInlineElementBox() const { return false; } |
| 89 | virtual bool isInlineFlowBox() const { return false; } |
| 90 | virtual bool isInlineTextBox() const { return false; } |
| 91 | virtual bool isRootInlineBox() const { return false; } |
| 92 | virtual bool isSVGInlineTextBox() const { return false; } |
| 93 | virtual bool isSVGInlineFlowBox() const { return false; } |
| 94 | virtual bool isSVGRootInlineBox() const { return false; } |
| 95 | |
| 96 | bool hasVirtualLogicalHeight() const { return m_bitfields.hasVirtualLogicalHeight(); } |
| 97 | void setHasVirtualLogicalHeight() { m_bitfields.setHasVirtualLogicalHeight(true); } |
| 98 | virtual float virtualLogicalHeight() const |
| 99 | { |
| 100 | ASSERT_NOT_REACHED(); |
| 101 | return 0; |
| 102 | } |
| 103 | |
| 104 | bool isHorizontal() const { return m_bitfields.isHorizontal(); } |
| 105 | void setIsHorizontal(bool isHorizontal) { m_bitfields.setIsHorizontal(isHorizontal); } |
| 106 | |
| 107 | virtual FloatRect calculateBoundaries() const |
| 108 | { |
| 109 | ASSERT_NOT_REACHED(); |
| 110 | return FloatRect(); |
| 111 | } |
| 112 | |
| 113 | bool isConstructed() { return m_bitfields.constructed(); } |
| 114 | virtual void setConstructed() { m_bitfields.setConstructed(true); } |
| 115 | |
| 116 | void (bool = true) { m_bitfields.setExtracted(extracted); } |
| 117 | |
| 118 | void setIsFirstLine(bool firstLine) { m_bitfields.setFirstLine(firstLine); } |
| 119 | bool isFirstLine() const { return m_bitfields.firstLine(); } |
| 120 | |
| 121 | void removeFromParent(); |
| 122 | |
| 123 | InlineBox* nextOnLine() const { return m_next; } |
| 124 | InlineBox* prevOnLine() const { return m_prev; } |
| 125 | void setNextOnLine(InlineBox* next) |
| 126 | { |
| 127 | ASSERT(m_parent || !next); |
| 128 | m_next = next; |
| 129 | } |
| 130 | void setPrevOnLine(InlineBox* prev) |
| 131 | { |
| 132 | ASSERT(m_parent || !prev); |
| 133 | m_prev = prev; |
| 134 | } |
| 135 | bool nextOnLineExists() const; |
| 136 | bool previousOnLineExists() const; |
| 137 | |
| 138 | virtual bool isLeaf() const { return true; } |
| 139 | |
| 140 | InlineBox* nextLeafChild() const; |
| 141 | InlineBox* prevLeafChild() const; |
| 142 | |
| 143 | // Helper functions for editing and hit-testing code. |
| 144 | // FIXME: These two functions should be moved to RenderedPosition once the code to convert between |
| 145 | // Position and inline box, offset pair is moved to RenderedPosition. |
| 146 | InlineBox* nextLeafChildIgnoringLineBreak() const; |
| 147 | InlineBox* prevLeafChildIgnoringLineBreak() const; |
| 148 | |
| 149 | // FIXME: Hide this once all callers are using tighter types. |
| 150 | RenderObject& renderer() const { return m_renderer; } |
| 151 | |
| 152 | InlineFlowBox* parent() const |
| 153 | { |
| 154 | assertNotDeleted(); |
| 155 | ASSERT_WITH_SECURITY_IMPLICATION(!m_hasBadParent); |
| 156 | return m_parent; |
| 157 | } |
| 158 | void setParent(InlineFlowBox* par) { m_parent = par; } |
| 159 | |
| 160 | const RootInlineBox& root() const; |
| 161 | RootInlineBox& root(); |
| 162 | |
| 163 | // x() is the left side of the box in the containing block's coordinate system. |
| 164 | void setX(float x) { m_topLeft.setX(x); } |
| 165 | float x() const { return m_topLeft.x(); } |
| 166 | float left() const { return m_topLeft.x(); } |
| 167 | |
| 168 | // y() is the top side of the box in the containing block's coordinate system. |
| 169 | void setY(float y) { m_topLeft.setY(y); } |
| 170 | float y() const { return m_topLeft.y(); } |
| 171 | float top() const { return m_topLeft.y(); } |
| 172 | |
| 173 | const FloatPoint& topLeft() const { return m_topLeft; } |
| 174 | |
| 175 | float width() const { return isHorizontal() ? logicalWidth() : logicalHeight(); } |
| 176 | float height() const { return isHorizontal() ? logicalHeight() : logicalWidth(); } |
| 177 | FloatSize size() const { return FloatSize(width(), height()); } |
| 178 | float right() const { return left() + width(); } |
| 179 | float bottom() const { return top() + height(); } |
| 180 | |
| 181 | // The logicalLeft position is the left edge of the line box in a horizontal line and the top edge in a vertical line. |
| 182 | float logicalLeft() const { return isHorizontal() ? m_topLeft.x() : m_topLeft.y(); } |
| 183 | float logicalRight() const { return logicalLeft() + logicalWidth(); } |
| 184 | void setLogicalLeft(float left) |
| 185 | { |
| 186 | if (isHorizontal()) |
| 187 | setX(left); |
| 188 | else |
| 189 | setY(left); |
| 190 | } |
| 191 | |
| 192 | // The logicalTop[ position is the top edge of the line box in a horizontal line and the left edge in a vertical line. |
| 193 | float logicalTop() const { return isHorizontal() ? m_topLeft.y() : m_topLeft.x(); } |
| 194 | float logicalBottom() const { return logicalTop() + logicalHeight(); } |
| 195 | void setLogicalTop(float top) |
| 196 | { |
| 197 | if (isHorizontal()) |
| 198 | setY(top); |
| 199 | else |
| 200 | setX(top); |
| 201 | } |
| 202 | |
| 203 | // The logical width is our extent in the line's overall inline direction, i.e., width for horizontal text and height for vertical text. |
| 204 | void setLogicalWidth(float w) { m_logicalWidth = w; } |
| 205 | float logicalWidth() const { return m_logicalWidth; } |
| 206 | |
| 207 | // The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text. |
| 208 | float logicalHeight() const; |
| 209 | |
| 210 | FloatRect logicalFrameRect() const { return isHorizontal() ? FloatRect(m_topLeft.x(), m_topLeft.y(), m_logicalWidth, logicalHeight()) : FloatRect(m_topLeft.y(), m_topLeft.x(), m_logicalWidth, logicalHeight()); } |
| 211 | FloatRect frameRect() const { return FloatRect(topLeft(), size()); } |
| 212 | |
| 213 | WEBCORE_EXPORT virtual int baselinePosition(FontBaseline baselineType) const; |
| 214 | WEBCORE_EXPORT virtual LayoutUnit lineHeight() const; |
| 215 | |
| 216 | WEBCORE_EXPORT virtual int caretMinOffset() const; |
| 217 | WEBCORE_EXPORT virtual int caretMaxOffset() const; |
| 218 | |
| 219 | unsigned char bidiLevel() const { return m_bitfields.bidiEmbeddingLevel(); } |
| 220 | void setBidiLevel(unsigned char level) { m_bitfields.setBidiEmbeddingLevel(level); } |
| 221 | TextDirection direction() const { return bidiLevel() % 2 ? TextDirection::RTL : TextDirection::LTR; } |
| 222 | bool isLeftToRightDirection() const { return direction() == TextDirection::LTR; } |
| 223 | int caretLeftmostOffset() const { return isLeftToRightDirection() ? caretMinOffset() : caretMaxOffset(); } |
| 224 | int caretRightmostOffset() const { return isLeftToRightDirection() ? caretMaxOffset() : caretMinOffset(); } |
| 225 | |
| 226 | virtual void clearTruncation() { } |
| 227 | |
| 228 | bool isDirty() const { return m_bitfields.dirty(); } |
| 229 | virtual void markDirty(bool dirty = true) { m_bitfields.setDirty(dirty); } |
| 230 | |
| 231 | WEBCORE_EXPORT virtual void dirtyLineBoxes(); |
| 232 | |
| 233 | WEBCORE_EXPORT virtual RenderObject::SelectionState selectionState(); |
| 234 | |
| 235 | WEBCORE_EXPORT virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const; |
| 236 | // visibleLeftEdge, visibleRightEdge are in the parent's coordinate system. |
| 237 | WEBCORE_EXPORT virtual float placeEllipsisBox(bool ltr, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool&); |
| 238 | |
| 239 | #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED |
| 240 | void setHasBadParent(); |
| 241 | void invalidateParentChildList(); |
| 242 | #endif |
| 243 | |
| 244 | bool visibleToHitTesting() const { return renderer().style().visibility() == Visibility::Visible && renderer().style().pointerEvents() != PointerEvents::None; } |
| 245 | |
| 246 | const RenderStyle& lineStyle() const { return m_bitfields.firstLine() ? renderer().firstLineStyle() : renderer().style(); } |
| 247 | |
| 248 | VerticalAlign verticalAlign() const { return lineStyle().verticalAlign(); } |
| 249 | |
| 250 | // Use with caution! The type is not checked! |
| 251 | RenderBoxModelObject* boxModelObject() const |
| 252 | { |
| 253 | if (!is<RenderText>(m_renderer)) |
| 254 | return &downcast<RenderBoxModelObject>(m_renderer); |
| 255 | return nullptr; |
| 256 | } |
| 257 | |
| 258 | FloatPoint locationIncludingFlipping() const; |
| 259 | void flipForWritingMode(FloatRect&) const; |
| 260 | FloatPoint flipForWritingMode(const FloatPoint&) const; |
| 261 | void flipForWritingMode(LayoutRect&) const; |
| 262 | LayoutPoint flipForWritingMode(const LayoutPoint&) const; |
| 263 | |
| 264 | bool knownToHaveNoOverflow() const { return m_bitfields.knownToHaveNoOverflow(); } |
| 265 | void clearKnownToHaveNoOverflow(); |
| 266 | |
| 267 | bool dirOverride() const { return m_bitfields.dirOverride(); } |
| 268 | void setDirOverride(bool dirOverride) { m_bitfields.setDirOverride(dirOverride); } |
| 269 | |
| 270 | void setExpansion(float newExpansion) |
| 271 | { |
| 272 | m_logicalWidth -= m_expansion; |
| 273 | m_expansion = newExpansion; |
| 274 | m_logicalWidth += m_expansion; |
| 275 | } |
| 276 | void setExpansionWithoutGrowing(float newExpansion) |
| 277 | { |
| 278 | ASSERT(!m_expansion); |
| 279 | m_expansion = newExpansion; |
| 280 | } |
| 281 | float expansion() const { return m_expansion; } |
| 282 | |
| 283 | void setHasHyphen(bool hasHyphen) { m_bitfields.setHasEllipsisBoxOrHyphen(hasHyphen); } |
| 284 | void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(canHaveLeadingExpansion); } |
| 285 | void setCanHaveTrailingExpansion(bool canHaveTrailingExpansion) { m_bitfields.setCanHaveTrailingExpansion(canHaveTrailingExpansion); } |
| 286 | void setForceTrailingExpansion() { m_bitfields.setForceTrailingExpansion(true); } |
| 287 | void setForceLeadingExpansion() { m_bitfields.setForceLeadingExpansion(true); } |
| 288 | |
| 289 | private: |
| 290 | InlineBox* m_next { nullptr }; // The next element on the same line as us. |
| 291 | InlineBox* m_prev { nullptr }; // The previous element on the same line as us. |
| 292 | |
| 293 | InlineFlowBox* m_parent { nullptr }; // The box that contains us. |
| 294 | |
| 295 | RenderObject& m_renderer; |
| 296 | |
| 297 | private: |
| 298 | float m_logicalWidth { 0 }; |
| 299 | float m_expansion { 0 }; |
| 300 | FloatPoint m_topLeft; |
| 301 | |
| 302 | #define ADD_BOOLEAN_BITFIELD(name, Name) \ |
| 303 | private:\ |
| 304 | unsigned m_##name : 1;\ |
| 305 | public:\ |
| 306 | bool name() const { return m_##name; }\ |
| 307 | void set##Name(bool name) { m_##name = name; }\ |
| 308 | |
| 309 | class InlineBoxBitfields { |
| 310 | public: |
| 311 | explicit InlineBoxBitfields(bool firstLine = false, bool constructed = false, bool dirty = false, bool = false, bool isHorizontal = true) |
| 312 | : m_firstLine(firstLine) |
| 313 | , m_constructed(constructed) |
| 314 | , m_bidiEmbeddingLevel(0) |
| 315 | , m_dirty(dirty) |
| 316 | , m_extracted(extracted) |
| 317 | , m_hasVirtualLogicalHeight(false) |
| 318 | , m_isHorizontal(isHorizontal) |
| 319 | , m_endsWithBreak(false) |
| 320 | , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false) |
| 321 | , m_canHaveTrailingExpansion(false) |
| 322 | , m_knownToHaveNoOverflow(true) |
| 323 | , m_hasEllipsisBoxOrHyphen(false) |
| 324 | , m_dirOverride(false) |
| 325 | , m_behavesLikeText(false) |
| 326 | , m_forceTrailingExpansion(false) |
| 327 | , m_forceLeadingExpansion(false) |
| 328 | , m_determinedIfNextOnLineExists(false) |
| 329 | , m_nextOnLineExists(false) |
| 330 | { |
| 331 | } |
| 332 | |
| 333 | // Some of these bits are actually for subclasses and moved here to compact the structures. |
| 334 | // for this class |
| 335 | ADD_BOOLEAN_BITFIELD(firstLine, FirstLine); |
| 336 | ADD_BOOLEAN_BITFIELD(constructed, Constructed); |
| 337 | |
| 338 | private: |
| 339 | unsigned m_bidiEmbeddingLevel : 6; // The maximium bidi level is 62: http://unicode.org/reports/tr9/#Explicit_Levels_and_Directions |
| 340 | |
| 341 | public: |
| 342 | unsigned char bidiEmbeddingLevel() const { return m_bidiEmbeddingLevel; } |
| 343 | void setBidiEmbeddingLevel(unsigned char bidiEmbeddingLevel) { m_bidiEmbeddingLevel = bidiEmbeddingLevel; } |
| 344 | |
| 345 | ADD_BOOLEAN_BITFIELD(dirty, Dirty); |
| 346 | ADD_BOOLEAN_BITFIELD(, Extracted); |
| 347 | ADD_BOOLEAN_BITFIELD(hasVirtualLogicalHeight, HasVirtualLogicalHeight); |
| 348 | ADD_BOOLEAN_BITFIELD(isHorizontal, IsHorizontal); |
| 349 | // for RootInlineBox |
| 350 | ADD_BOOLEAN_BITFIELD(endsWithBreak, EndsWithBreak); // Whether the line ends with a <br>. |
| 351 | // shared between RootInlineBox and InlineTextBox |
| 352 | ADD_BOOLEAN_BITFIELD(hasSelectedChildrenOrCanHaveLeadingExpansion, HasSelectedChildrenOrCanHaveLeadingExpansion); |
| 353 | ADD_BOOLEAN_BITFIELD(canHaveTrailingExpansion, CanHaveTrailingExpansion); |
| 354 | ADD_BOOLEAN_BITFIELD(knownToHaveNoOverflow, KnownToHaveNoOverflow); |
| 355 | ADD_BOOLEAN_BITFIELD(hasEllipsisBoxOrHyphen, HasEllipsisBoxOrHyphen); |
| 356 | // for InlineTextBox |
| 357 | ADD_BOOLEAN_BITFIELD(dirOverride, DirOverride); |
| 358 | ADD_BOOLEAN_BITFIELD(behavesLikeText, BehavesLikeText); // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes, br. |
| 359 | ADD_BOOLEAN_BITFIELD(forceTrailingExpansion, ForceTrailingExpansion); |
| 360 | ADD_BOOLEAN_BITFIELD(forceLeadingExpansion, ForceLeadingExpansion); |
| 361 | |
| 362 | private: |
| 363 | mutable unsigned m_determinedIfNextOnLineExists : 1; |
| 364 | |
| 365 | public: |
| 366 | bool determinedIfNextOnLineExists() const { return m_determinedIfNextOnLineExists; } |
| 367 | void setDeterminedIfNextOnLineExists(bool determinedIfNextOnLineExists) const { m_determinedIfNextOnLineExists = determinedIfNextOnLineExists; } |
| 368 | |
| 369 | private: |
| 370 | mutable unsigned m_nextOnLineExists : 1; |
| 371 | |
| 372 | public: |
| 373 | bool nextOnLineExists() const { return m_nextOnLineExists; } |
| 374 | void setNextOnLineExists(bool nextOnLineExists) const { m_nextOnLineExists = nextOnLineExists; } |
| 375 | }; |
| 376 | #undef ADD_BOOLEAN_BITFIELD |
| 377 | |
| 378 | InlineBoxBitfields m_bitfields; |
| 379 | |
| 380 | protected: |
| 381 | explicit InlineBox(RenderObject& renderer) |
| 382 | : m_renderer(renderer) |
| 383 | { |
| 384 | } |
| 385 | |
| 386 | InlineBox(RenderObject& renderer, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed, bool dirty, bool , bool isHorizontal, InlineBox* next, InlineBox* prev, InlineFlowBox* parent) |
| 387 | : m_next(next) |
| 388 | , m_prev(prev) |
| 389 | , m_parent(parent) |
| 390 | , m_renderer(renderer) |
| 391 | , m_logicalWidth(logicalWidth) |
| 392 | , m_topLeft(topLeft) |
| 393 | , m_bitfields(firstLine, constructed, dirty, extracted, isHorizontal) |
| 394 | { |
| 395 | } |
| 396 | |
| 397 | // For RootInlineBox |
| 398 | bool endsWithBreak() const { return m_bitfields.endsWithBreak(); } |
| 399 | void setEndsWithBreak(bool endsWithBreak) { m_bitfields.setEndsWithBreak(endsWithBreak); } |
| 400 | bool hasEllipsisBox() const { return m_bitfields.hasEllipsisBoxOrHyphen(); } |
| 401 | bool hasSelectedChildren() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); } |
| 402 | void setHasSelectedChildren(bool hasSelectedChildren) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(hasSelectedChildren); } |
| 403 | void setHasEllipsisBox(bool hasEllipsisBox) { m_bitfields.setHasEllipsisBoxOrHyphen(hasEllipsisBox); } |
| 404 | |
| 405 | // For InlineTextBox |
| 406 | bool hasHyphen() const { return m_bitfields.hasEllipsisBoxOrHyphen(); } |
| 407 | bool canHaveLeadingExpansion() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); } |
| 408 | bool canHaveTrailingExpansion() const { return m_bitfields.canHaveTrailingExpansion(); } |
| 409 | bool forceTrailingExpansion() const { return m_bitfields.forceTrailingExpansion(); } |
| 410 | bool forceLeadingExpansion() const { return m_bitfields.forceLeadingExpansion(); } |
| 411 | |
| 412 | // For InlineFlowBox and InlineTextBox |
| 413 | bool () const { return m_bitfields.extracted(); } |
| 414 | |
| 415 | protected: |
| 416 | |
| 417 | #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED |
| 418 | private: |
| 419 | static constexpr unsigned deletionSentinelNotDeletedValue = 0xF0F0F0F0U; |
| 420 | static constexpr unsigned deletionSentinelDeletedValue = 0xF0DEADF0U; |
| 421 | unsigned m_deletionSentinel { deletionSentinelNotDeletedValue }; |
| 422 | bool m_hasBadParent { false }; |
| 423 | protected: |
| 424 | bool m_isEverInChildList { true }; |
| 425 | #endif |
| 426 | }; |
| 427 | |
| 428 | #if ASSERT_WITH_SECURITY_IMPLICATION_DISABLED |
| 429 | |
| 430 | inline InlineBox::~InlineBox() |
| 431 | { |
| 432 | } |
| 433 | |
| 434 | inline void InlineBox::assertNotDeleted() const |
| 435 | { |
| 436 | } |
| 437 | |
| 438 | #endif |
| 439 | |
| 440 | } // namespace WebCore |
| 441 | |
| 442 | #define SPECIALIZE_TYPE_TRAITS_INLINE_BOX(ToValueTypeName, predicate) \ |
| 443 | SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \ |
| 444 | static bool isType(const WebCore::InlineBox& box) { return box.predicate; } \ |
| 445 | SPECIALIZE_TYPE_TRAITS_END() |
| 446 | |
| 447 | #if ENABLE(TREE_DEBUGGING) |
| 448 | // Outside the WebCore namespace for ease of invocation from the debugger. |
| 449 | void showNodeTree(const WebCore::InlineBox*); |
| 450 | void showLineTree(const WebCore::InlineBox*); |
| 451 | #endif |
| 452 | |