blob: f0e42926c3fd65e1967546614566457139bcb80e [file] [log] [blame]
#define LOG_TAG "PictureLayerContent"
#define LOG_NDEBUG 1
#include "config.h"
#include "PictureLayerContent.h"
#include "AndroidLog.h"
#include "InspectorCanvas.h"
#include "SkPicture.h"
#include <dlfcn.h>
#include "SkDevice.h"
namespace WebCore {
PictureLayerContent::PictureLayerContent(SkPicture* picture)
: m_picture(picture)
, m_checkedContent(false)
, m_hasText(true)
{
SkSafeRef(m_picture);
}
PictureLayerContent::PictureLayerContent(const PictureLayerContent& content)
: m_picture(content.m_picture)
, m_checkedContent(content.m_checkedContent)
, m_hasText(content.m_hasText)
{
SkSafeRef(m_picture);
}
PictureLayerContent::~PictureLayerContent()
{
SkSafeUnref(m_picture);
}
int PictureLayerContent::width()
{
if (!m_picture)
return 0;
return m_picture->width();
}
int PictureLayerContent::height()
{
if (!m_picture)
return 0;
return m_picture->height();
}
void PictureLayerContent::checkForOptimisations()
{
if (!m_checkedContent)
maxZoomScale(); // for now only check the maximum scale for painting
}
float PictureLayerContent::maxZoomScale()
{
if (m_checkedContent)
return m_hasText ? 1e6 : 1.0;
// Let's check if we have text or not. If we don't, we can limit
// ourselves to scale 1!
InspectorBounder inspectorBounder;
InspectorCanvas checker(&inspectorBounder, m_picture);
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config,
m_picture->width(),
m_picture->height());
checker.setBitmapDevice(bitmap);
checker.drawPicture(*m_picture);
m_hasText = checker.hasText();
if (!checker.hasContent()) {
// no content to draw, discard picture so UI / tile generation
// doesn't bother with it
SkSafeUnref(m_picture);
m_picture = 0;
}
m_checkedContent = true;
return m_hasText ? 1e6 : 1.0;
}
void PictureLayerContent::draw(SkCanvas* canvas)
{
if (!m_picture)
return;
TRACE_METHOD();
android::Mutex::Autolock lock(m_drawLock);
SkRect r = SkRect::MakeWH(width(), height());
canvas->clipRect(r);
canvas->drawPicture(*m_picture);
}
void PictureLayerContent::serialize(SkWStream* stream)
{
if (!m_picture)
return;
m_picture->serialize(stream);
}
LegacyPictureLayerContent::LegacyPictureLayerContent(SkMemoryStream* pictureStream) {
m_legacyPicture = NULL;
m_width = 0;
m_height = 0;
// load legacy skia lib (all functions hidden except ones defined below)
m_legacyLib = dlopen("libskia_legacy.so", RTLD_LAZY);
*reinterpret_cast<void**>(&m_createPictureProc) = dlsym(m_legacyLib, "legacy_skia_create_picture");
*reinterpret_cast<void**>(&m_deletePictureProc) = dlsym(m_legacyLib, "legacy_skia_delete_picture");
*reinterpret_cast<void**>(&m_drawPictureProc) = dlsym(m_legacyLib, "legacy_skia_draw_picture");
const char* error = dlerror();
if (error) {
SkDebugf("Unable to load legacy lib: %s", error);
sk_throw();
}
// call into library to create picture and set width and height
const int streamLength = pictureStream->getLength() - pictureStream->peek();
int bytesRead = m_createPictureProc(pictureStream->getAtPos(), streamLength,
&m_legacyPicture, &m_width, &m_height);
pictureStream->skip(bytesRead);
}
LegacyPictureLayerContent::~LegacyPictureLayerContent() {
if (m_legacyLib) {
if (m_legacyPicture) {
m_deletePictureProc(m_legacyPicture);
}
dlclose(m_legacyLib);
}
}
void LegacyPictureLayerContent::draw(SkCanvas* canvas) {
if (!m_legacyPicture) {
return;
}
// if this is an InspectorCanvas we need to at least draw something to
// ensure that the canvas is not discarded. (We perform a no-op text
// draw in order to trigger the InspectorCanvas into performing high
// fidelity rendering while zooming.
SkPaint paint;
canvas->drawText(NULL, 0, 0, 0, paint);
// decompose the canvas into basics
void* matrixStorage = malloc(canvas->getTotalMatrix().flatten(NULL));
void* clipStorage = malloc(canvas->getTotalClip().flatten(NULL));
canvas->getTotalMatrix().flatten(matrixStorage);
canvas->getTotalClip().flatten(clipStorage);
const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true);
bitmap.lockPixels();
// pass picture, matrix, clip, and bitmap
m_drawPictureProc(m_legacyPicture, matrixStorage, clipStorage,
bitmap.width(), bitmap.height(), bitmap.getConfig(),
bitmap.rowBytes(), bitmap.getPixels());
bitmap.unlockPixels();
free(matrixStorage);
free(clipStorage);
}
} // namespace WebCore