1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "platform/PlatformExport.h"
9 #include "platform/graphics/ContiguousContainer.h"
10 #include "platform/graphics/paint/DisplayItemClient.h"
11 #include "wtf/Assertions.h"
12 #include "wtf/PassOwnPtr.h"
15 #include "wtf/text/StringBuilder.h"
16 #include "wtf/text/WTFString.h"
22 class GraphicsContext
;
23 class WebDisplayItemList
;
25 class PLATFORM_EXPORT DisplayItem
{
28 // Must be kept in sync with core/paint/PaintPhase.h.
32 // A display item type uniquely identifies a display item of a client.
33 // Some display item types can be categorized using the following directives:
35 // - enum value <Category>First;
36 // - enum values of the category, first of which should equal <Category>First;
37 // (for ease of maintenance, the values should be in alphabetic order)
38 // - enum value <Category>Last which should be equal to the last of the enum values of the category
39 // - DEFINE_CATEGORY_METHODS(<Category>) to define is<Category>Type(Type) and is<Category>() methods.
41 // A category or subset of a category can contain types each of which corresponds to a PaintPhase:
43 // - enum value <Category>[<Subset>]PaintPhaseFirst;
44 // - enum value <Category>[<Subset>]PaintPhaseLast = <Category>[<Subset>]PaintPhaseFirst + PaintPhaseMax;
45 // - DEFINE_PAINT_PHASE_CONVERSION_METHOD(<Category>[<Subset>]) to define
46 // paintPhaseTo<Category>[<Subset>]Type(PaintPhase) method.
48 // A category can be derived from another category, containing types each of which corresponds to a
49 // value of the latter category:
51 // - enum value <Category>First;
52 // - enum value <Category>Last = <Category>First + <BaseCategory>Last - <BaseCategory>First;
53 // - DEFINE_CONVERSION_METHODS(<Category>, <category>, <BaseCategory>, <baseCategory>) to define methods to
54 // convert types between the categories;
57 DrawingPaintPhaseFirst
= DrawingFirst
,
58 DrawingPaintPhaseLast
= DrawingFirst
+ PaintPhaseMax
,
59 BoxDecorationBackground
,
67 PageWidgetDelegateBackgroundFallback
,
69 PopupListBoxBackground
,
71 PrintedContentBackground
,
72 PrintedContentLineBoundary
,
73 PrintedContentPDFURLRect
,
78 ScrollbarBackButtonEnd
,
79 ScrollbarBackButtonStart
,
83 ScrollbarForwardButtonEnd
,
84 ScrollbarForwardButtonStart
,
85 ScrollbarForwardTrack
,
86 ScrollbarHorizontal
, // For ScrollbarThemeMacNonOverlayAPI only.
89 ScrollbarTrackBackground
,
90 ScrollbarVertical
, // For ScrollbarThemeMacNonOverlayAPI only.
93 TableCellBackgroundFromContainers
,
94 TableCellBackgroundFromSelfPaintingRow
,
95 // Table collapsed borders can be painted together (e.g., left & top) but there are at most 4 phases of collapsed
96 // border painting for a single cell. To disambiguate these phases of collapsed border painting, a mask is used.
97 // TableCollapsedBorderBase can be larger than TableCollapsedBorderUnalignedBase to ensure the base lower bits are 0's.
98 TableCollapsedBorderUnalignedBase
,
99 TableCollapsedBorderBase
= (((TableCollapsedBorderUnalignedBase
- 1) >> 4) + 1) << 4,
100 TableCollapsedBorderLast
= TableCollapsedBorderBase
+ 0x0f,
104 DrawingLast
= WebFont
,
107 CachedDrawingLast
= CachedDrawingFirst
+ DrawingLast
- DrawingFirst
,
110 ClipBoxPaintPhaseFirst
= ClipFirst
,
111 ClipBoxPaintPhaseLast
= ClipBoxPaintPhaseFirst
+ PaintPhaseMax
,
112 ClipColumnBoundsPaintPhaseFirst
,
113 ClipColumnBoundsPaintPhaseLast
= ClipColumnBoundsPaintPhaseFirst
+ PaintPhaseMax
,
114 ClipLayerFragmentPaintPhaseFirst
,
115 ClipLayerFragmentPaintPhaseLast
= ClipLayerFragmentPaintPhaseFirst
+ PaintPhaseMax
,
116 ClipFileUploadControlRect
,
117 ClipFrameToVisibleContentRect
,
120 ClipLayerColumnBounds
,
124 ClipLayerOverflowControls
,
126 ClipPopupListBoxFrame
,
128 PageWidgetDelegateClip
,
130 ClipLast
= ClipPrintedPage
,
133 EndClipLast
= EndClipFirst
+ ClipLast
- ClipFirst
,
136 FloatClipPaintPhaseFirst
= FloatClipFirst
,
137 FloatClipPaintPhaseLast
= FloatClipFirst
+ PaintPhaseMax
,
138 FloatClipLast
= FloatClipPaintPhaseLast
,
140 EndFloatClipLast
= EndFloatClipFirst
+ FloatClipLast
- FloatClipFirst
,
143 ScrollPaintPhaseFirst
= ScrollFirst
,
144 ScrollPaintPhaseLast
= ScrollPaintPhaseFirst
+ PaintPhaseMax
,
145 ScrollLast
= ScrollPaintPhaseLast
,
147 EndScrollLast
= EndScrollFirst
+ ScrollLast
- ScrollFirst
,
150 Transform3DElementTransform
= Transform3DFirst
,
151 Transform3DLast
= Transform3DElementTransform
,
153 EndTransform3DLast
= EndTransform3DFirst
+ Transform3DLast
- Transform3DFirst
,
165 BeginFixedPositionContainer
,
166 EndFixedPositionContainer
,
173 TypeLast
= UninitializedType
176 static_assert(TableCollapsedBorderBase
>= TableCollapsedBorderUnalignedBase
, "TableCollapsedBorder types overlap with other types");
177 static_assert((TableCollapsedBorderBase
& 0xf) == 0, "The lowest 4 bits of TableCollapsedBorderBase should be zero");
178 // Bits or'ed onto TableCollapsedBorderBase to generate a real table collapsed border type.
179 enum TableCollspaedBorderSides
{
180 TableCollapsedBorderTop
= 1 << 0,
181 TableCollapsedBorderRight
= 1 << 1,
182 TableCollapsedBorderBottom
= 1 << 2,
183 TableCollapsedBorderLeft
= 1 << 3,
186 DisplayItem(const DisplayItemClientWrapper
& client
, Type type
, size_t derivedSize
)
187 : m_client(client
.displayItemClient())
190 , m_derivedSize(derivedSize
)
191 , m_skippedCache(false)
193 , m_clientDebugString(client
.debugName())
196 // derivedSize must fit in m_derivedSize.
197 // If it doesn't, enlarge m_derivedSize and fix this assert.
198 ASSERT_WITH_SECURITY_IMPLICATION(derivedSize
< (1 << 8));
199 ASSERT_WITH_SECURITY_IMPLICATION(derivedSize
>= sizeof(*this));
202 virtual ~DisplayItem() { }
204 // Ids are for matching new DisplayItems with existing DisplayItems.
206 Id(const DisplayItemClient client
, const Type type
, const unsigned scope
)
211 bool matches(const DisplayItem
& item
) const
213 // We should always convert to non-cached types before matching.
214 ASSERT(!isCachedType(item
.m_type
));
215 ASSERT(!isCachedType(type
));
216 return client
== item
.m_client
217 && type
== item
.m_type
218 && scope
== item
.m_scope
;
221 const DisplayItemClient client
;
223 const unsigned scope
;
226 // Convert cached type to non-cached type (e.g., Type::CachedSVGImage -> Type::SVGImage).
227 static Type
nonCachedType(Type type
)
229 if (isCachedDrawingType(type
))
230 return cachedDrawingTypeToDrawingType(type
);
231 if (type
== CachedSubsequence
)
232 return BeginSubsequence
;
236 // Return the Id with cached type converted to non-cached type.
237 Id
nonCachedId() const
239 return Id(m_client
, nonCachedType(m_type
), m_scope
);
242 virtual void replay(GraphicsContext
&) { }
244 DisplayItemClient
client() const { return m_client
; }
245 Type
type() const { return m_type
; }
247 void setScope(unsigned scope
) { m_scope
= scope
; }
248 unsigned scope() { return m_scope
; }
250 // Size of this object in memory, used to move it with memcpy.
251 // This is not sizeof(*this), because it needs to account for the size of
252 // the derived class (i.e. runtime type). Derived classes are expected to
253 // supply this to the DisplayItem constructor.
254 size_t derivedSize() const { return m_derivedSize
; }
256 // For DisplayItemList only. Painters should use DisplayItemCacheSkipper instead.
257 void setSkippedCache() { m_skippedCache
= true; }
258 bool skippedCache() const { return m_skippedCache
; }
260 virtual void appendToWebDisplayItemList(WebDisplayItemList
*) const { }
262 // See comments of enum Type for usage of the following macros.
263 #define DEFINE_CATEGORY_METHODS(Category) \
264 static bool is##Category##Type(Type type) { return type >= Category##First && type <= Category##Last; } \
265 bool is##Category() const { return is##Category##Type(type()); }
267 #define DEFINE_CONVERSION_METHODS(Category1, category1, Category2, category2) \
268 static Type category1##TypeTo##Category2##Type(Type type) \
270 static_assert(Category1##Last - Category1##First == Category2##Last - Category2##First, \
271 "Categories " #Category1 " and " #Category2 " should have same number of enum values. See comments of DisplayItem::Type"); \
272 ASSERT(is##Category1##Type(type)); \
273 return static_cast<Type>(type - Category1##First + Category2##First); \
275 static Type category2##TypeTo##Category1##Type(Type type) \
277 ASSERT(is##Category2##Type(type)); \
278 return static_cast<Type>(type - Category2##First + Category1##First); \
281 #define DEFINE_PAIRED_CATEGORY_METHODS(Category, category) \
282 DEFINE_CATEGORY_METHODS(Category) \
283 DEFINE_CATEGORY_METHODS(End##Category) \
284 DEFINE_CONVERSION_METHODS(Category, category, End##Category, end##Category)
286 #define DEFINE_PAINT_PHASE_CONVERSION_METHOD(Category) \
287 static Type paintPhaseTo##Category##Type(int paintPhase) \
289 static_assert(Category##PaintPhaseLast - Category##PaintPhaseFirst == PaintPhaseMax, \
290 "Invalid paint-phase-based category " #Category ". See comments of DisplayItem::Type"); \
291 return static_cast<Type>(paintPhase + Category##PaintPhaseFirst); \
294 DEFINE_CATEGORY_METHODS(Drawing
)
295 DEFINE_PAINT_PHASE_CONVERSION_METHOD(Drawing
)
296 DEFINE_CATEGORY_METHODS(CachedDrawing
)
297 DEFINE_CONVERSION_METHODS(Drawing
, drawing
, CachedDrawing
, cachedDrawing
)
299 DEFINE_PAIRED_CATEGORY_METHODS(Clip
, clip
)
300 DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipLayerFragment
)
301 DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipBox
)
302 DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipColumnBounds
)
304 DEFINE_PAIRED_CATEGORY_METHODS(FloatClip
, floatClip
)
305 DEFINE_PAINT_PHASE_CONVERSION_METHOD(FloatClip
)
307 DEFINE_PAIRED_CATEGORY_METHODS(Scroll
, scroll
)
308 DEFINE_PAINT_PHASE_CONVERSION_METHOD(Scroll
)
310 DEFINE_PAIRED_CATEGORY_METHODS(Transform3D
, transform3D
);
312 static bool isCachedType(Type type
) { return isCachedDrawingType(type
) || type
== CachedSubsequence
; }
313 bool isCached() const { return isCachedType(m_type
); }
314 static bool isCacheableType(Type type
) { return isDrawingType(type
) || type
== BeginSubsequence
; }
315 bool isCacheable() const { return !skippedCache() && isCacheableType(m_type
); }
317 virtual bool isBegin() const { return false; }
318 virtual bool isEnd() const { return false; }
321 virtual bool isEndAndPairedWith(DisplayItem::Type otherType
) const { return false; }
322 virtual bool equals(const DisplayItem
& other
) const
324 return m_client
== other
.m_client
325 && m_scope
== other
.m_scope
326 && m_type
== other
.m_type
327 && m_derivedSize
== other
.m_derivedSize
328 && m_skippedCache
== other
.m_skippedCache
;
332 virtual bool drawsContent() const { return false; }
334 bool isValid() const { return m_client
; }
337 static WTF::String
typeAsDebugString(DisplayItem::Type
);
338 const WTF::String
& clientDebugString() const { return m_clientDebugString
; }
339 void setClientDebugString(const WTF::String
& s
) { m_clientDebugString
= s
; }
340 WTF::String
asDebugString() const;
341 virtual void dumpPropertiesAsDebugString(WTF::StringBuilder
&) const;
345 // The default DisplayItem constructor is only used by
346 // ContiguousContainer::appendByMoving where an invalid DisplaItem is
347 // constructed at the source location.
348 template <typename T
, unsigned alignment
> friend class ContiguousContainer
;
353 , m_type(UninitializedType
)
354 , m_derivedSize(sizeof(*this))
355 , m_skippedCache(false)
358 const DisplayItemClient m_client
;
360 static_assert(TypeLast
< (1 << 16), "DisplayItem::Type should fit in 16 bits");
361 const Type m_type
: 16;
362 const unsigned m_derivedSize
: 8; // size of the actual derived class
363 unsigned m_skippedCache
: 1;
366 WTF::String m_clientDebugString
;
370 class PLATFORM_EXPORT PairedBeginDisplayItem
: public DisplayItem
{
372 PairedBeginDisplayItem(const DisplayItemClientWrapper
& client
, Type type
, size_t derivedSize
) : DisplayItem(client
, type
, derivedSize
) { }
375 bool isBegin() const final
{ return true; }
378 class PLATFORM_EXPORT PairedEndDisplayItem
: public DisplayItem
{
380 PairedEndDisplayItem(const DisplayItemClientWrapper
& client
, Type type
, size_t derivedSize
) : DisplayItem(client
, type
, derivedSize
) { }
383 bool isEndAndPairedWith(DisplayItem::Type otherType
) const override
= 0;
387 bool isEnd() const final
{ return true; }
392 #endif // DisplayItem_h