static void rerecord(const SkPicture& src, SkBBHFactory* bbhFactory) { SkPictureRecorder recorder; if (FLAGS_skr) { src.draw(recorder.EXPERIMENTAL_beginRecording(src.width(), src.height(), bbhFactory)); } else { src.draw(recorder.beginRecording(src.width(), src.height(), bbhFactory)); } SkAutoTUnref<SkPicture> pic(recorder.endRecording()); }
static void draw(const EXPERIMENTAL::SkPlayback& skr, const SkPicture& skp, SkCanvas* canvas) { if (FLAGS_skr) { skr.draw(canvas); } else { skp.draw(canvas); } }
void ImageBuffer::copyRecordingToCanvas(GraphicsContext* paintContext, const IntRect& r) const { SkCanvas* paintCanvas = paintContext->platformContext()->mCanvas; SkPicture* canvasRecording = context()->platformContext()->getRecordingPicture(); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); const SkIRect& clipBounds = paintCanvas->getTotalClip().getBounds(); SkRect rect; int saveCount = 0; if( (clipBounds.width() > r.width() * 2 ) || (clipBounds.height() > r.height() * 2)) { rect.set(r.location().x(), r.location().y(),r.width(), r.height()); saveCount = paintCanvas->saveLayer(&rect, &paint); } else saveCount = paintCanvas->saveLayer(0, &paint); paintCanvas->translate(r.location().x(), r.location().y()); // Resize to the now known viewport. paintCanvas->scale(r.width() / width(), r.height() / height()); // Draw the canvas recording into the layer recording canvas. canvasRecording->draw(paintCanvas); context()->platformContext()->clearRecording(); paintCanvas->restoreToCount(saveCount); }
static void draw(JNIEnv* env, jobject, jlong canvasHandle, jlong pictureHandle) { SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle); SkPicture* picture = reinterpret_cast<SkPicture*>(pictureHandle); SkASSERT(canvas); SkASSERT(picture); picture->draw(canvas); }
// Extract the command ops from the input SkPicture static void gets_ops(SkPicture& input, SkTDArray<DrawType>* ops) { SkDebugCanvas debugCanvas(input.width(), input.height()); debugCanvas.setBounds(input.width(), input.height()); input.draw(&debugCanvas); ops->setCount(debugCanvas.getSize()); for (int i = 0; i < debugCanvas.getSize(); ++i) { (*ops)[i] = debugCanvas.getDrawCommandAt(i)->getType(); } }
static void testOne(const SkString& filename) { #if DEBUG_SHOW_TEST_NAME SkString testName(filename); const char http[] = "http"; if (testName.startsWith(http)) { testName.remove(0, sizeof(http) - 1); } while (testName.startsWith("_")) { testName.remove(0, 1); } const char dotSkp[] = ".skp"; if (testName.endsWith(dotSkp)) { size_t len = testName.size(); testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1); } testName.prepend("skp"); testName.append("1"); strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH); #endif SkString path; make_filepath(&path, pictDir, filename); SkFILEStream stream(path.c_str()); if (!stream.isValid()) { return; } SkPicture* pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory); if (!pic) { SkDebugf("unable to decode %s\n", filename.c_str()); return; } int width = pic->width(); int height = pic->height(); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); bool success = bitmap.allocPixels(); if (!success) { SkDebugf("unable to allocate bitmap for %s\n", filename.c_str()); return; } SkCanvas canvas(bitmap); SkString pngName(filename); pngName.remove(pngName.size() - 3, 3); pngName.append("png"); for (int i = 0; i < 2; ++i) { bool useOp = i ? true : false; canvas.setAllowSimplifyClip(useOp); pic->draw(&canvas); SkString outFile; make_filepath(&outFile, useOp ? outSkpClipDir : outOldClipDir, pngName); SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); } SkDELETE(pic); }
void SampleWindow::afterChildren(SkCanvas* orig) { switch (fCanvasType) { case kRaster_CanvasType: break; case kPicture_CanvasType: if (true) { SkPicture* pict = new SkPicture(*fPicture); fPicture->unref(); orig->drawPicture(*pict); pict->unref(); } else if (true) { SkDynamicMemoryWStream ostream; fPicture->serialize(&ostream); fPicture->unref(); SkMemoryStream istream(ostream.getStream(), ostream.getOffset()); SkPicture pict(&istream); orig->drawPicture(pict); } else { fPicture->draw(orig); fPicture->unref(); } fPicture = NULL; break; #ifdef SK_SUPPORT_GL case kOpenGL_CanvasType: glFlush(); delete fGLCanvas; fGLCanvas = NULL; #ifdef USE_OFFSCREEN reverseRedAndBlue(orig->getDevice()->accessBitmap(true)); #endif break; #endif } // if ((fScrollTestX | fScrollTestY) != 0) { const SkBitmap& bm = orig->getDevice()->accessBitmap(true); int dx = fScrollTestX * 7; int dy = fScrollTestY * 7; SkIRect r; SkRegion inval; r.set(50, 50, 50+100, 50+100); bm.scrollRect(&r, dx, dy, &inval); paint_rgn(bm, r, inval); } }
// Do the commands in 'input' match the supplied pattern? Note: this is a pretty // heavy-weight operation since we are drawing the picture into a debug canvas // to extract the commands. static bool check_pattern(SkPicture& input, const SkTDArray<DrawType> &pattern) { SkDebugCanvas debugCanvas(input.width(), input.height()); debugCanvas.setBounds(input.width(), input.height()); input.draw(&debugCanvas); if (pattern.count() != debugCanvas.getSize()) { return false; } for (int i = 0; i < pattern.count(); ++i) { if (pattern[i] != debugCanvas.getDrawCommandAt(i)->getType()) { return false; } } return true; }
virtual void onDraw(SkCanvas* canvas) { int offset = 35000; int extents = 1000; // We record a picture of huge vertical extents in which we clear the canvas to red, create // a 'extents' by 'extents' round rect clip at a vertical offset of 'offset', then draw // green into that. SkPicture pict; SkCanvas* rec = pict.beginRecording(100, offset + extents); rec->drawColor(0xffff0000); rec->save(); SkRect r = { SkIntToScalar(-extents), SkIntToScalar(offset - extents), SkIntToScalar(extents), SkIntToScalar(offset + extents) }; SkPath p; p.addRoundRect(r, 5, 5); rec->clipPath(p, SkRegion::kIntersect_Op, true); rec->drawColor(0xff00ff00); rec->restore(); pict.endRecording(); // Next we play that picture into another picture of the same size. SkPicture pict2; pict.draw(pict2.beginRecording(100, offset + extents)); pict2.endRecording(); // Finally we play the part of that second picture that should be green into the canvas. canvas->save(); canvas->translate(SkIntToScalar(extents / 2), SkIntToScalar(-(offset - extents / 2))); pict2.draw(canvas); canvas->restore(); // If the image is red, we erroneously decided the clipPath was empty and didn't record // the green drawColor, if it's green we're all good. }
/** * Called only by render_picture(). */ static bool render_picture_internal(const SkString& inputPath, const SkString* outputDir, sk_tools::PictureRenderer& renderer, SkBitmap** out) { SkString inputFilename; sk_tools::get_basename(&inputFilename, inputPath); SkString outputDirString; if (NULL != outputDir && outputDir->size() > 0 && !FLAGS_writeEncodedImages) { outputDirString.set(*outputDir); } SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkDebugf("Could not open file %s\n", inputPath.c_str()); return false; } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else if (FLAGS_writeEncodedImages) { SkASSERT(!FLAGS_writePath.isEmpty()); reset_image_file_base_name(inputFilename); proc = &write_image_to_file; } else { proc = &SkImageDecoder::DecodeMemory; } SkDebugf("deserializing... %s\n", inputPath.c_str()); SkPicture* picture = SkPicture::CreateFromStream(&inputStream, proc); if (NULL == picture) { SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str()); return false; } while (FLAGS_bench_record) { const int kRecordFlags = 0; SkPicture other; picture->draw(other.beginRecording(picture->width(), picture->height(), kRecordFlags)); other.endRecording(); } for (int i = 0; i < FLAGS_clone; ++i) { SkPicture* clone = picture->clone(); SkDELETE(picture); picture = clone; } SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(), inputPath.c_str()); renderer.init(picture, &outputDirString, &inputFilename, FLAGS_writeChecksumBasedFilenames); if (FLAGS_preprocess) { if (NULL != renderer.getCanvas()) { renderer.getCanvas()->EXPERIMENTAL_optimize(picture); } } renderer.setup(); bool success = renderer.render(out); if (!success) { SkDebugf("Failed to render %s\n", inputFilename.c_str()); } renderer.end(); SkDELETE(picture); return success; }
void SkRecorder::drawPicture(SkPicture& picture) { picture.draw(this); }
CanvasLayer::CanvasLayer(const CanvasLayer& layer) : LayerAndroid(layer) , m_canvas(0) , m_bitmap(0) , m_gpuCanvas(0) { init(); if (!layer.m_canvas) { // The canvas has already been destroyed - this shouldn't happen ALOGW("Creating a CanvasLayer for a destroyed canvas!"); m_visibleContentRect = IntRect(); m_offsetFromRenderer = IntSize(); m_texture->setHwAccelerated(false); return; } // We are making a copy for the UI, sync the interesting bits m_visibleContentRect = layer.visibleContentRect(); m_offsetFromRenderer = layer.offsetFromRenderer(); bool previousState = m_texture->hasValidTexture(); if(layer.m_canvas->isUsingGpuRendering()) return; ImageBuffer* imageBuffer = layer.m_canvas->buffer(); if (!previousState && layer.m_dirtyCanvas.isEmpty() && imageBuffer && !(imageBuffer->drawsUsingRecording())) { // We were previously in software and don't have anything new to draw, // so stay in software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); } else { if(imageBuffer && imageBuffer->drawsUsingRecording() && !layer.m_canvas->isUsingGpuRendering()) { bool canUseGpuRendering = imageBuffer->canUseGpuRendering(); if(canUseGpuRendering && layer.m_canvas->canUseGpuRendering()) { layer.m_canvas->enableGpuRendering(); CanvasLayer::setGpuCanvasStatus(layer.uniqueId(), true); } } // If recording is being used if(imageBuffer && imageBuffer->drawsUsingRecording()) { GraphicsContext* gc = imageBuffer->context(); //SkPicture* canvasRecording = gc->platformContext()->getRecordingPicture(); SkPicture* canvasRecording = CanvasLayer::getRecordingPicture(this); SkBitmap* bitmap = CanvasLayer::getRecordingBitmap(this); SkCanvas* canvas = CanvasLayer::getRecordingCanvas(this); if(canvasRecording == NULL) return; if(bitmap == NULL || bitmap->width() != canvasRecording->width() || bitmap->height() != canvasRecording->height()) { SkBitmap* newBitmap = new SkBitmap(); newBitmap->setConfig(SkBitmap::kARGB_8888_Config, canvasRecording->width(), canvasRecording->height()); newBitmap->allocPixels(); newBitmap->eraseColor(0); CanvasLayer::setRecordingBitmap(newBitmap, this); bitmap = newBitmap; if(canvas != NULL) canvas->setBitmapDevice(*bitmap); } if(canvas == NULL) { canvas = new SkCanvas(); canvas->setBitmapDevice(*bitmap); CanvasLayer::setRecordingCanvas(canvas, this); } canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); canvasRecording->draw(canvas); if (!m_texture->uploadImageBitmap(bitmap)) { //SLOGD("+++++++++++++++++++++ Didn't upload bitmap .. fall back to software"); // TODO:: Fix this } } else { if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) { // Blargh, no surface texture or ImageBuffer - fall back to software m_bitmap = layer.bitmap(); SkSafeRef(m_bitmap); // Merge the canvas invals with the layer's invals to repaint the needed // tiles. SkRegion::Iterator iter(layer.m_dirtyCanvas); const IntPoint& offset = m_visibleContentRect.location(); for (; !iter.done(); iter.next()) { SkIRect diff = iter.rect(); diff.fLeft += offset.x(); diff.fRight += offset.x(); diff.fTop += offset.y(); diff.fBottom += offset.y(); m_dirtyRegion.op(diff, SkRegion::kUnion_Op); } }else{ ImageBuffer* imageBuffer = layer.m_canvas->buffer(); bool recordingCanvasEnabled = layer.m_canvas->isRecordingCanvasEnabled(); if(recordingCanvasEnabled && imageBuffer && imageBuffer->isAnimating()){ SLOGD("[%s] Animation detected. Converting the HTML5 canvas buffer to a SkPicture.", __FUNCTION__); imageBuffer->convertToRecording(); } }//End of non-recording } if (previousState != m_texture->hasValidTexture()) { // Need to do a full inval of the canvas content as we are mode switching m_dirtyRegion.op(m_visibleContentRect.x(), m_visibleContentRect.y(), m_visibleContentRect.maxX(), m_visibleContentRect.maxY(), SkRegion::kUnion_Op); } } }
/** * Called only by render_picture(). */ static bool render_picture_internal(const SkString& inputPath, const SkString* writePath, const SkString* mismatchPath, sk_tools::PictureRenderer& renderer, SkBitmap** out) { SkString inputFilename = SkOSPath::SkBasename(inputPath.c_str()); SkString writePathString; if (NULL != writePath && writePath->size() > 0 && !FLAGS_writeEncodedImages) { writePathString.set(*writePath); } SkString mismatchPathString; if (NULL != mismatchPath && mismatchPath->size() > 0) { mismatchPathString.set(*mismatchPath); } SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkDebugf("Could not open file %s\n", inputPath.c_str()); return false; } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else if (FLAGS_writeEncodedImages) { SkASSERT(!FLAGS_writePath.isEmpty()); reset_image_file_base_name(inputFilename); proc = &write_image_to_file; } else { proc = &SkImageDecoder::DecodeMemory; } SkDebugf("deserializing... %s\n", inputPath.c_str()); SkPicture* picture = SkPicture::CreateFromStream(&inputStream, proc); if (NULL == picture) { SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str()); return false; } while (FLAGS_bench_record) { SkPictureRecorder recorder; picture->draw(recorder.beginRecording(picture->width(), picture->height(), NULL, 0)); SkAutoTUnref<SkPicture> other(recorder.endRecording()); } SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(), inputPath.c_str()); renderer.init(picture, &writePathString, &mismatchPathString, &inputFilename, FLAGS_writeChecksumBasedFilenames); if (FLAGS_preprocess) { if (NULL != renderer.getCanvas()) { renderer.getCanvas()->EXPERIMENTAL_optimize(renderer.getPicture()); } } renderer.setup(); renderer.enableWrites(); bool success = renderer.render(out); if (!success) { SkDebugf("Failed to render %s\n", inputFilename.c_str()); } renderer.end(); SkDELETE(picture); return success; }