ScopeRecorder::ScopeRecorder(GraphicsContext& context, const DisplayItemClientWrapper& object)
    : m_displayItemList(context.displayItemList())
    , m_object(object)
{
    if (!RuntimeEnabledFeatures::slimmingPaintEnabled())
        return;

    ASSERT(m_displayItemList);
    m_displayItemList->beginScope(object.displayItemClient());
}
DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClientWrapper& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& cullRect)
    : m_context(context)
    , m_displayItemClient(displayItemClient)
    , m_displayItemType(displayItemType)
#if ENABLE(ASSERT)
    , m_displayItemPosition(m_context.displayItemList()->newDisplayItems().size())
    , m_underInvalidationCheckingMode(DrawingDisplayItem::CheckPicture)
#endif
{
    ASSERT(context.displayItemList());
    if (context.displayItemList()->displayItemConstructionIsDisabled())
        return;

    // Must check DrawingRecorder::useCachedDrawingIfPossible before creating the DrawingRecorder.
    ASSERT((RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && context.displayItemList()->paintOffsetWasInvalidated(displayItemClient.displayItemClient()))
        || RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()
        || !useCachedDrawingIfPossible(m_context, m_displayItemClient, m_displayItemType));

    ASSERT(DisplayItem::isDrawingType(displayItemType));

#if ENABLE(ASSERT)
    context.setInDrawingRecorder(true);
#endif

    context.beginRecording(cullRect);

#if ENABLE(ASSERT)
    if (RuntimeEnabledFeatures::slimmingPaintStrictCullRectClippingEnabled()) {
        // Skia depends on the cull rect containing all of the display item commands. When strict
        // cull rect clipping is enabled, make this explicit. This allows us to identify potential
        // incorrect cull rects that might otherwise be masked due to Skia internal optimizations.
        context.save();
        IntRect verificationClip = enclosingIntRect(cullRect);
        // Expand the verification clip by one pixel to account for Skia's SkCanvas::getClipBounds()
        // expansion, used in testing cull rects.
        // TODO(schenney) This is not the best place to do this. Ideally, we would expand by one pixel
        // in device (pixel) space, but to do that we would need to add the verification mode to Skia.
        verificationClip.inflate(1);
        context.clipRect(verificationClip, NotAntiAliased, SkRegion::kIntersect_Op);
    }
#endif
}
bool DrawingRecorder::useCachedDrawingIfPossible(GraphicsContext& context, const DisplayItemClientWrapper& client, DisplayItem::Type type)
{
    ASSERT(context.displayItemList());
    ASSERT(DisplayItem::isDrawingType(type));

    if (context.displayItemList()->displayItemConstructionIsDisabled())
        return false;

    if (!context.displayItemList()->clientCacheIsValid(client.displayItemClient()))
        return false;

    context.displayItemList()->createAndAppend<CachedDisplayItem>(client, DisplayItem::drawingTypeToCachedDrawingType(type));

#if ENABLE(ASSERT)
    // When under-invalidation checking is enabled, we output CachedDrawing display item
    // followed by the display item containing forced painting.
    if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
        return false;
#endif

    return true;
}
SubtreeRecorder::SubtreeRecorder(GraphicsContext& context, const DisplayItemClientWrapper& client, int paintPhase)
    : m_displayItemList(context.displayItemList())
    , m_client(client)
    , m_paintPhase(paintPhase)
    , m_canUseCache(false)
#if ENABLE(ASSERT)
    , m_checkedCanUseCache(false)
#endif
{
    if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
        return;

    ASSERT(m_displayItemList);

    // TODO(wangxianzhu): Implement subtree caching.

    if (!m_canUseCache)
        m_displayItemList->createAndAppend<BeginSubtreeDisplayItem>(m_client, DisplayItem::paintPhaseToBeginSubtreeType(paintPhase));
}