blob: b630917eaa2a5586fd27e8eff7d7945cd2f1bc18 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/graphics/paint/DrawingDisplayItem.h"
#include "platform/graphics/GraphicsContext.h"
#include "public/platform/WebDisplayItemList.h"
#if ENABLE(ASSERT)
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkStream.h"
#endif
namespace blink {
void DrawingDisplayItem::replay(GraphicsContext& context) const
{
if (m_picture)
context.drawPicture(m_picture.get());
}
void DrawingDisplayItem::appendToWebDisplayItemList(const IntRect& visualRect, WebDisplayItemList* list) const
{
if (m_picture)
list->appendDrawingItem(visualRect, m_picture.get());
}
bool DrawingDisplayItem::drawsContent() const
{
return m_picture;
}
#ifndef NDEBUG
void DrawingDisplayItem::dumpPropertiesAsDebugString(WTF::StringBuilder& stringBuilder) const
{
DisplayItem::dumpPropertiesAsDebugString(stringBuilder);
if (m_picture) {
stringBuilder.append(WTF::String::format(", rect: [%f,%f,%f,%f]",
m_picture->cullRect().x(), m_picture->cullRect().y(),
m_picture->cullRect().width(), m_picture->cullRect().height()));
}
}
#endif
#if ENABLE(ASSERT)
static bool bitmapIsAllZero(const SkBitmap& bitmap)
{
bitmap.lockPixels();
bool result = true;
for (int x = 0; result && x < bitmap.width(); ++x) {
for (int y = 0; result && y < bitmap.height(); ++y) {
if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT) {
result = false;
break;
}
}
}
bitmap.unlockPixels();
return result;
}
bool DrawingDisplayItem::equals(const DisplayItem& other) const
{
if (!DisplayItem::equals(other))
return false;
RefPtr<const SkPicture> picture = this->picture();
RefPtr<const SkPicture> otherPicture = static_cast<const DrawingDisplayItem&>(other).picture();
if (!picture && !otherPicture)
return true;
if (!picture || !otherPicture)
return false;
switch (getUnderInvalidationCheckingMode()) {
case DrawingDisplayItem::CheckPicture: {
if (picture->approximateOpCount() != otherPicture->approximateOpCount())
return false;
SkDynamicMemoryWStream pictureSerialized;
picture->serialize(&pictureSerialized);
SkDynamicMemoryWStream otherPictureSerialized;
otherPicture->serialize(&otherPictureSerialized);
if (pictureSerialized.bytesWritten() != otherPictureSerialized.bytesWritten())
return false;
RefPtr<SkData> oldData = adoptRef(otherPictureSerialized.copyToData());
RefPtr<SkData> newData = adoptRef(pictureSerialized.copyToData());
return oldData->equals(newData.get());
}
case DrawingDisplayItem::CheckBitmap: {
SkRect rect = picture->cullRect();
if (rect != otherPicture->cullRect())
return false;
SkBitmap bitmap;
bitmap.allocPixels(SkImageInfo::MakeN32Premul(rect.width(), rect.height()));
SkCanvas canvas(bitmap);
canvas.translate(-rect.x(), -rect.y());
canvas.drawPicture(otherPicture.get());
SkPaint diffPaint;
diffPaint.setXfermodeMode(SkXfermode::kDifference_Mode);
canvas.drawPicture(picture.get(), nullptr, &diffPaint);
return bitmapIsAllZero(bitmap);
}
default:
ASSERT_NOT_REACHED();
}
return false;
}
#endif // ENABLE(ASSERT)
} // namespace blink