1 #define LOG_TAG "PictureLayerContent" 2 #define LOG_NDEBUG 1 3 4 #include "config.h" 5 #include "PictureLayerContent.h" 6 7 #include "AndroidLog.h" 8 #include "InspectorCanvas.h" 9 #include "SkPicture.h" 10 11 #include <dlfcn.h> 12 #include "SkDevice.h" 13 14 namespace WebCore { 15 16 PictureLayerContent::PictureLayerContent(SkPicture* picture) 17 : m_picture(picture) 18 , m_checkedContent(false) 19 , m_hasText(true) 20 { 21 SkSafeRef(m_picture); 22 } 23 24 PictureLayerContent::PictureLayerContent(const PictureLayerContent& content) 25 : m_picture(content.m_picture) 26 , m_checkedContent(content.m_checkedContent) 27 , m_hasText(content.m_hasText) 28 { 29 SkSafeRef(m_picture); 30 } 31 32 PictureLayerContent::~PictureLayerContent() 33 { 34 SkSafeUnref(m_picture); 35 } 36 37 int PictureLayerContent::width() 38 { 39 if (!m_picture) 40 return 0; 41 return m_picture->width(); 42 } 43 44 int PictureLayerContent::height() 45 { 46 if (!m_picture) 47 return 0; 48 return m_picture->height(); 49 } 50 51 void PictureLayerContent::checkForOptimisations() 52 { 53 if (!m_checkedContent) 54 maxZoomScale(); // for now only check the maximum scale for painting 55 } 56 57 float PictureLayerContent::maxZoomScale() 58 { 59 if (m_checkedContent) 60 return m_hasText ? 1e6 : 1.0; 61 62 // Let's check if we have text or not. If we don't, we can limit 63 // ourselves to scale 1! 64 SkBitmap bitmap; 65 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 66 m_picture->width(), 67 m_picture->height()); 68 InspectorBounder inspectorBounder; 69 InspectorCanvas checker(&inspectorBounder, m_picture, bitmap); 70 checker.drawPicture(*m_picture); 71 m_hasText = checker.hasText(); 72 if (!checker.hasContent()) { 73 // no content to draw, discard picture so UI / tile generation 74 // doesn't bother with it 75 SkSafeUnref(m_picture); 76 m_picture = 0; 77 } 78 79 m_checkedContent = true; 80 81 return m_hasText ? 1e6 : 1.0; 82 } 83 84 void PictureLayerContent::draw(SkCanvas* canvas) 85 { 86 if (!m_picture) 87 return; 88 89 TRACE_METHOD(); 90 android::Mutex::Autolock lock(m_drawLock); 91 SkRect r = SkRect::MakeWH(width(), height()); 92 canvas->clipRect(r); 93 canvas->drawPicture(*m_picture); 94 } 95 96 void PictureLayerContent::serialize(SkWStream* stream) 97 { 98 if (!m_picture) 99 return; 100 m_picture->serialize(stream); 101 } 102 103 104 LegacyPictureLayerContent::LegacyPictureLayerContent(SkMemoryStream* pictureStream) { 105 m_legacyPicture = NULL; 106 m_width = 0; 107 m_height = 0; 108 109 // load legacy skia lib (all functions hidden except ones defined below) 110 m_legacyLib = dlopen("libskia_legacy.so", RTLD_LAZY); 111 *reinterpret_cast<void**>(&m_createPictureProc) = dlsym(m_legacyLib, "legacy_skia_create_picture"); 112 *reinterpret_cast<void**>(&m_deletePictureProc) = dlsym(m_legacyLib, "legacy_skia_delete_picture"); 113 *reinterpret_cast<void**>(&m_drawPictureProc) = dlsym(m_legacyLib, "legacy_skia_draw_picture"); 114 115 const char* error = dlerror(); 116 if (error) { 117 SkDebugf("Unable to load legacy lib: %s", error); 118 sk_throw(); 119 } 120 121 // call into library to create picture and set width and height 122 const int streamLength = pictureStream->getLength() - pictureStream->peek(); 123 int bytesRead = m_createPictureProc(pictureStream->getAtPos(), streamLength, 124 &m_legacyPicture, &m_width, &m_height); 125 pictureStream->skip(bytesRead); 126 } 127 128 LegacyPictureLayerContent::~LegacyPictureLayerContent() { 129 if (m_legacyLib) { 130 if (m_legacyPicture) { 131 m_deletePictureProc(m_legacyPicture); 132 } 133 dlclose(m_legacyLib); 134 } 135 } 136 137 void LegacyPictureLayerContent::draw(SkCanvas* canvas) { 138 if (!m_legacyPicture) { 139 return; 140 } 141 142 // if this is an InspectorCanvas we need to at least draw something to 143 // ensure that the canvas is not discarded. (We perform a no-op text 144 // draw in order to trigger the InspectorCanvas into performing high 145 // fidelity rendering while zooming. 146 SkPaint paint; 147 canvas->drawText(NULL, 0, 0, 0, paint); 148 149 // decompose the canvas into basics 150 void* matrixStorage = malloc(canvas->getTotalMatrix().writeToMemory(NULL)); 151 void* clipStorage = malloc(canvas->getTotalClip().writeToMemory(NULL)); 152 153 canvas->getTotalMatrix().writeToMemory(matrixStorage); 154 canvas->getTotalClip().writeToMemory(clipStorage); 155 156 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true); 157 bitmap.lockPixels(); 158 159 // pass picture, matrix, clip, and bitmap 160 m_drawPictureProc(m_legacyPicture, matrixStorage, clipStorage, 161 bitmap.width(), bitmap.height(), bitmap.getConfig(), 162 bitmap.rowBytes(), bitmap.getPixels()); 163 164 165 bitmap.unlockPixels(); 166 free(matrixStorage); 167 free(clipStorage); 168 } 169 170 } // namespace WebCore 171