virtual Result onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&, SkPMColor ctableEntries[], int* ctableCount) override { SkMemoryStream stream(fData->data(), fData->size(), false); SkAutoTUnref<BareMemoryAllocator> allocator(SkNEW_ARGS(BareMemoryAllocator, (info, pixels, rowBytes))); fDecoder->setAllocator(allocator); fDecoder->setRequireUnpremultipliedColors(kUnpremul_SkAlphaType == info.alphaType()); SkBitmap bm; const SkImageDecoder::Result result = fDecoder->decode(&stream, &bm, info.colorType(), SkImageDecoder::kDecodePixels_Mode); if (SkImageDecoder::kFailure == result) { return kInvalidInput; } SkASSERT(info.colorType() == bm.info().colorType()); if (kIndex_8_SkColorType == info.colorType()) { SkASSERT(ctableEntries); SkColorTable* ctable = bm.getColorTable(); if (NULL == ctable) { return kInvalidConversion; } const int count = ctable->count(); memcpy(ctableEntries, ctable->readColors(), count * sizeof(SkPMColor)); *ctableCount = count; } if (SkImageDecoder::kPartialSuccess == result) { return kIncompleteInput; } return kSuccess; }
SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { printf("Started\n"); SkCommandLineFlags::Parse(argc, argv); // Get the default Isolate created at startup. Isolate* isolate = Isolate::GetCurrent(); Global* global = new Global(isolate); // Set up things to look like a browser by creating // a console object that invokes our print function. const char* startupScript = "function Console() {}; \n" "Console.prototype.log = function() { \n" " var args = Array.prototype.slice.call(arguments).join(' '); \n" " print(args); \n" "}; \n" "console = new Console(); \n"; if (!global->parseScript(startupScript)) { printf("Failed to parse startup script: %s.\n", FLAGS_infile[0]); exit(1); } const char* script = "function onDraw(canvas) { \n" " canvas.fillStyle = '#00FF00'; \n" " canvas.fillRect(20, 20, 100, 100); \n" " canvas.inval(); \n" "} \n"; SkAutoTUnref<SkData> data; if (FLAGS_infile.count()) { data.reset(SkData::NewFromFileName(FLAGS_infile[0])); script = static_cast<const char*>(data->data()); } if (NULL == script) { printf("Could not load file: %s.\n", FLAGS_infile[0]); exit(1); } Path2D::AddToGlobal(global); if (!global->parseScript(script)) { printf("Failed to parse file: %s.\n", FLAGS_infile[0]); exit(1); } JsContext* jsContext = new JsContext(global); if (!jsContext->initialize()) { printf("Failed to initialize.\n"); exit(1); } SkV8ExampleWindow* win = new SkV8ExampleWindow(hwnd, jsContext); global->setWindow(win); return win; }
/* * Modulo internal errors, this should always succeed *if* the matrix is downscaling * (in this case, we have the inverse, so it succeeds if fInvMatrix is upscaling) */ bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmapProvider& provider) { SkASSERT(fQuality <= kMedium_SkFilterQuality); if (fQuality != kMedium_SkFilterQuality) { return false; } // Our default return state is to downgrade the request to Low, w/ or w/o setting fBitmap // to a valid bitmap. fQuality = kLow_SkFilterQuality; SkSize invScaleSize; if (!fInvMatrix.decomposeScale(&invScaleSize, nullptr)) { return false; } // Use the largest (non-inverse) scale, to ensure anisotropic consistency. SkASSERT(invScaleSize.width() >= 0 && invScaleSize.height() >= 0); const SkScalar invScale = SkTMin(invScaleSize.width(), invScaleSize.height()); if (invScale > SK_Scalar1) { fCurrMip.reset(SkMipMapCache::FindAndRef(provider.makeCacheDesc())); if (nullptr == fCurrMip.get()) { SkBitmap orig; if (!provider.asBitmap(&orig)) { return false; } fCurrMip.reset(SkMipMapCache::AddAndRef(orig)); if (nullptr == fCurrMip.get()) { return false; } } // diagnostic for a crasher... if (nullptr == fCurrMip->data()) { sk_throw(); } SkScalar levelScale = SkScalarInvert(invScale); SkMipMap::Level level; if (fCurrMip->extractLevel(levelScale, &level)) { const SkSize& invScaleFixup = level.fScale; fInvMatrix.postScale(invScaleFixup.width(), invScaleFixup.height()); // todo: if we could wrap the fCurrMip in a pixelref, then we could just install // that here, and not need to explicitly track it ourselves. return fResultBitmap.installPixels(level.fPixmap); } else { // failed to extract, so release the mipmap fCurrMip.reset(nullptr); } } return false; }
/* * Modulo internal errors, this should always succeed *if* the matrix is downscaling * (in this case, we have the inverse, so it succeeds if fInvMatrix is upscaling) */ bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBitmap) { SkASSERT(fQuality <= kMedium_SkFilterQuality); if (fQuality != kMedium_SkFilterQuality) { return false; } // Our default return state is to downgrade the request to Low, w/ or w/o setting fBitmap // to a valid bitmap. fQuality = kLow_SkFilterQuality; SkSize invScaleSize; if (!fInvMatrix.decomposeScale(&invScaleSize, NULL)) { return false; } SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height()); if (invScale > SK_Scalar1) { fCurrMip.reset(SkMipMapCache::FindAndRef(origBitmap)); if (NULL == fCurrMip.get()) { fCurrMip.reset(SkMipMapCache::AddAndRef(origBitmap)); if (NULL == fCurrMip.get()) { return false; } } // diagnostic for a crasher... if (NULL == fCurrMip->data()) { sk_throw(); } SkScalar levelScale = SkScalarInvert(invScale); SkMipMap::Level level; if (fCurrMip->extractLevel(levelScale, &level)) { SkScalar invScaleFixup = level.fScale; fInvMatrix.postScale(invScaleFixup, invScaleFixup); const SkImageInfo info = origBitmap.info().makeWH(level.fWidth, level.fHeight); // todo: if we could wrap the fCurrMip in a pixelref, then we could just install // that here, and not need to explicitly track it ourselves. return fResultBitmap.installPixels(info, level.fPixels, level.fRowBytes); } else { // failed to extract, so release the mipmap fCurrMip.reset(NULL); } } return false; }
bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], SkYUVColorSpace* colorSpace) override { SkMemoryStream stream(fData->data(), fData->size(), false); return fDecoder->decodeYUV8Planes(&stream, sizes, planes, rowBytes, colorSpace); }
static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey, const SkBitmap& bm, const GrSurfaceDesc& desc) { // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding SkPixelRef* pixelRef = bm.pixelRef(); if ((NULL == pixelRef) || (pixelRef->info().width() != bm.info().width()) || (pixelRef->info().height() != bm.info().height())) { return NULL; } const bool useCache = optionalKey.isValid(); SkYUVPlanesCache::Info yuvInfo; SkAutoTUnref<SkCachedData> cachedData; SkAutoMalloc storage; if (useCache) { cachedData.reset(SkYUVPlanesCache::FindAndRef(pixelRef->getGenerationID(), &yuvInfo)); } void* planes[3]; if (cachedData.get()) { planes[0] = (void*)cachedData->data(); planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0]; planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1]; } else { // Fetch yuv plane sizes for memory allocation. Here, width and height can be // rounded up to JPEG block size and be larger than the image's width and height. if (!pixelRef->getYUV8Planes(yuvInfo.fSize, NULL, NULL, NULL)) { return NULL; } // Allocate the memory for YUV size_t totalSize(0); for (int i = 0; i < 3; ++i) { yuvInfo.fRowBytes[i] = yuvInfo.fSize[i].fWidth; yuvInfo.fSizeInMemory[i] = yuvInfo.fRowBytes[i] * yuvInfo.fSize[i].fHeight; totalSize += yuvInfo.fSizeInMemory[i]; } if (useCache) { cachedData.reset(SkResourceCache::NewCachedData(totalSize)); planes[0] = cachedData->writable_data(); } else { storage.reset(totalSize); planes[0] = storage.get(); } planes[1] = (uint8_t*)planes[0] + yuvInfo.fSizeInMemory[0]; planes[2] = (uint8_t*)planes[1] + yuvInfo.fSizeInMemory[1]; // Get the YUV planes and update plane sizes to actual image size if (!pixelRef->getYUV8Planes(yuvInfo.fSize, planes, yuvInfo.fRowBytes, &yuvInfo.fColorSpace)) { return NULL; } if (useCache) { // Decoding is done, cache the resulting YUV planes SkYUVPlanesCache::Add(pixelRef->getGenerationID(), cachedData, &yuvInfo); } } GrSurfaceDesc yuvDesc; yuvDesc.fConfig = kAlpha_8_GrPixelConfig; SkAutoTUnref<GrTexture> yuvTextures[3]; for (int i = 0; i < 3; ++i) { yuvDesc.fWidth = yuvInfo.fSize[i].fWidth; yuvDesc.fHeight = yuvInfo.fSize[i].fHeight; bool needsExactTexture = (yuvDesc.fWidth != yuvInfo.fSize[0].fWidth) || (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight); if (needsExactTexture) { yuvTextures[i].reset(ctx->textureProvider()->createTexture(yuvDesc, true)); } else { yuvTextures[i].reset(ctx->textureProvider()->createApproxTexture(yuvDesc)); } if (!yuvTextures[i] || !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight, yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) { return NULL; } } GrSurfaceDesc rtDesc = desc; rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; GrTexture* result = create_texture_for_bmp(ctx, optionalKey, rtDesc, pixelRef, NULL, 0); if (!result) { return NULL; } GrRenderTarget* renderTarget = result->asRenderTarget(); SkASSERT(renderTarget); GrPaint paint; SkAutoTUnref<GrFragmentProcessor> yuvToRgbProcessor(GrYUVtoRGBEffect::Create(paint.getProcessorDataManager(), yuvTextures[0], yuvTextures[1], yuvTextures[2], yuvInfo.fSize, yuvInfo.fColorSpace)); paint.addColorProcessor(yuvToRgbProcessor); SkRect r = SkRect::MakeWH(SkIntToScalar(yuvInfo.fSize[0].fWidth), SkIntToScalar(yuvInfo.fSize[0].fHeight)); GrDrawContext* drawContext = ctx->drawContext(); if (!drawContext) { return NULL; } drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r); return result; }