OvalTestView() { fSize.set(SK_Scalar1, SK_Scalar1); fBitmap.setConfig(SkBitmap::kARGB_8888_Config, kILimit, kILimit); fBitmap.allocPixels(); fInsideColor = SkPreMultiplyColor(SK_ColorRED); fOutsideColor = SkPreMultiplyColor(SK_ColorGREEN); this->setBGColor(0xFFDDDDDD); }
virtual void onPreDraw() { SkBitmap bm; if (kIndex_8_SkColorType == fColorType) { bm.allocPixels(SkImageInfo::MakeN32(W, H, fAlphaType)); } else { bm.allocPixels(SkImageInfo::Make(W, H, fColorType, fAlphaType)); } bm.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorBLACK : 0); onDrawIntoBitmap(bm); if (kIndex_8_SkColorType == fColorType) { convertToIndex666(bm, &fBitmap, fAlphaType); } else { fBitmap = bm; } fBitmap.setIsVolatile(fIsVolatile); }
// Verifies that the deferred canvas triggers a flush when its memory // limit is exceeded static void TestDeferredCanvasMemoryLimit(skiatest::Reporter* reporter) { SkBitmap store; store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); store.allocPixels(); MockDevice mockDevice(store); SkDeferredCanvas canvas(&mockDevice); canvas.setMaxRecordingStorage(160000); SkBitmap sourceImage; // 100 by 100 image, takes 40,000 bytes in memory sourceImage.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); sourceImage.allocPixels(); for (int i = 0; i < 5; i++) { sourceImage.notifyPixelsChanged(); // to force re-serialization canvas.drawBitmap(sourceImage, 0, 0, NULL); } REPORTER_ASSERT(reporter, mockDevice.fDrawBitmapCallCount == 4); }
static void TestBitmapHeap(skiatest::Reporter* reporter) { // Create a bitmap shader. SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); bm.allocPixels(); bm.eraseColor(SK_ColorRED); uint32_t* pixel = bm.getAddr32(1,0); *pixel = SK_ColorBLUE; SkShader* bitmapShader = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkAutoTUnref<SkShader> aur(bitmapShader); // Flatten, storing it in the bitmap heap. SkBitmapHeap heap(1, 1); SkChunkFlatController controller(1024); controller.setBitmapStorage(&heap); FlatDictionary dictionary(&controller); // Dictionary and heap start off empty. REPORTER_ASSERT(reporter, heap.count() == 0); REPORTER_ASSERT(reporter, dictionary.count() == 0); heap.deferAddingOwners(); int index = dictionary.find(*bitmapShader); heap.endAddingOwnersDeferral(true); // The dictionary and heap should now each have one entry. REPORTER_ASSERT(reporter, 1 == index); REPORTER_ASSERT(reporter, heap.count() == 1); REPORTER_ASSERT(reporter, dictionary.count() == 1); // The bitmap entry's refcount should be 1, then 0 after release. SkBitmapHeapEntry* entry = heap.getEntry(0); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 1); entry->releaseRef(); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(entry) == 0); // Now clear out the heap, after which it should be empty. heap.freeMemoryIfPossible(~0U); REPORTER_ASSERT(reporter, heap.count() == 0); // Now attempt to flatten the shader again. heap.deferAddingOwners(); index = dictionary.find(*bitmapShader); heap.endAddingOwnersDeferral(false); // The dictionary should report the same index since the new entry is identical. // The bitmap heap should contain the bitmap, but with no references. REPORTER_ASSERT(reporter, 1 == index); REPORTER_ASSERT(reporter, heap.count() == 1); REPORTER_ASSERT(reporter, SkBitmapHeapTester::GetRefCount(heap.getEntry(0)) == 0); }
jobject createBitmap(JNIEnv * env ,jobject obj,jint w,jint h,SkBitmap::Config config,jboolean hasAlpha,int isMuttable) { SkBitmap* bm = new SkBitmap(); bm->setConfig(config, w, h); bm->setIsOpaque(!hasAlpha); bm->allocPixels(); bm->eraseColor(0); //__android_log_print(ANDROID_LOG_DEBUG, "NativeBitmap", "Created bitmap %d has width = %d, height = %d",bm, bm->width(), bm->height()); jobject result = GraphicsJNI::createBitmap(env,bm,isMuttable,NULL,-1); return result; }
int main (int argc, char * const argv[]) { SkAutoGraphics ag; SkString path("skhello.png"); SkString text("Hello"); for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--help")) { show_help(); return 0; } if (!strcmp(argv[i], "-o")) { if (i == argc-1) { SkDebugf("ERROR: -o needs a following filename\n"); return -1; } path.set(argv[i+1]); i += 1; // skip the out dir name } else if (!strcmp(argv[i], "-t")) { if (i == argc-1) { SkDebugf("ERROR: -t needs a following string\n"); return -1; } text.set(argv[i+1]); i += 1; // skip the text string } } SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(30)); SkScalar width = paint.measureText(text.c_str(), text.size()); SkScalar spacing = paint.getFontSpacing(); int w = SkScalarRound(width) + 30; int h = SkScalarRound(spacing) + 30; SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h); bitmap.allocPixels(); SkCanvas canvas(bitmap); canvas.drawColor(SK_ColorWHITE); paint.setTextAlign(SkPaint::kCenter_Align); canvas.drawText(text.c_str(), text.size(), SkIntToScalar(w)/2, SkIntToScalar(h)*2/3, paint); bool success = SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); if (!success) { SkDebugf("--- failed to write %s\n", path.c_str()); } return !success; }
static void TestDeferredCanvasBitmapShaderNoLeak(skiatest::Reporter* reporter) { // This is a regression test for crbug.com/155875 // This test covers a code path that inserts bitmaps into the bitmap heap through the // flattening of SkBitmapProcShaders. The refcount in the bitmap heap is maintained through // the flattening and unflattening of the shader. SkBitmap store; store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); store.allocPixels(); SkDevice device(store); SkDeferredCanvas canvas(&device); // test will fail if nbIterations is not in sync with // BITMAPS_TO_KEEP in SkGPipeWrite.cpp const int nbIterations = 5; size_t bytesAllocated = 0; for(int pass = 0; pass < 2; ++pass) { for(int i = 0; i < nbIterations; ++i) { SkPaint paint; SkBitmap paintPattern; paintPattern.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); paintPattern.allocPixels(); paint.setShader(SkNEW_ARGS(SkBitmapProcShader, (paintPattern, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)))->unref(); canvas.drawPaint(paint); canvas.flush(); // In the first pass, memory allocation should be monotonically increasing as // the bitmap heap slots fill up. In the second pass memory allocation should be // stable as bitmap heap slots get recycled. size_t newBytesAllocated = canvas.storageAllocatedForRecording(); if (pass == 0) { REPORTER_ASSERT(reporter, newBytesAllocated > bytesAllocated); bytesAllocated = newBytesAllocated; } else { REPORTER_ASSERT(reporter, newBytesAllocated == bytesAllocated); } } } // All cached resources should be evictable since last canvas call was flush() canvas.freeMemoryIfPossible(~0); REPORTER_ASSERT(reporter, 0 == canvas.storageAllocatedForRecording()); }
static void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) { const SkIRect size = SkIRect::MakeWH(gWidth, gHeight); SkBitmap src; src.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); src.allocPixels(); src.eraseColor(SK_ColorBLACK); size_t srcSize = src.getSize(); size_t initialCacheSize = context->getGpuTextureCacheBytes(); int oldMaxNum; size_t oldMaxBytes; context->getTextureCacheLimits(&oldMaxNum, &oldMaxBytes); // Set the cache limits so we can fit 10 "src" images and the // max number of textures doesn't matter size_t maxCacheSize = initialCacheSize + 10*srcSize; context->setTextureCacheLimits(1000, maxCacheSize); SkBitmap readback; readback.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); readback.allocPixels(); for (int i = 0; i < 100; ++i) { canvas->drawBitmap(src, 0, 0); canvas->readPixels(size, &readback); // "modify" the src texture src.notifyPixelsChanged(); size_t curCacheSize = context->getGpuTextureCacheBytes(); // we should never go over the size limit REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize); } context->setTextureCacheLimits(oldMaxNum, oldMaxBytes); }
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); }
static SkBitmap createBitmapWithSpace(const SkBitmap& bitmap, int spaceWidth, int spaceHeight) { SkImageInfo info = bitmap.info(); info = SkImageInfo::Make(info.width() + spaceWidth, info.height() + spaceHeight, info.colorType(), kPremul_SkAlphaType); SkBitmap result; result.allocPixels(info); result.eraseColor(SK_ColorTRANSPARENT); bitmap.copyPixelsTo(reinterpret_cast<uint8_t*>(result.getPixels()), result.rowBytes() * result.height(), result.rowBytes()); return result; }
void TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap, uint32_t width, uint32_t height) { SkBitmap rgbaBitmap; rgbaBitmap.allocPixels(SkImageInfo::MakeN32(width, height, bitmap->alphaType())); rgbaBitmap.eraseColor(0); SkCanvas canvas(rgbaBitmap); canvas.drawBitmap(*bitmap, 0.0f, 0.0f, nullptr); uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), rgbaBitmap.bytesPerPixel(), width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels()); }
static void TestUnalignedQuery(skiatest::Reporter* reporter) { // Use SkTileGridPicture to generate a SkTileGrid with a helper SkTileGridPicture picture(10, 10, 20, 20); SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(8), SkIntToScalar(8)); SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(11), SkIntToScalar(11), SkIntToScalar(1), SkIntToScalar(1)); SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag); SkPaint paint; canvas->drawRect(rect1, paint); canvas->drawRect(rect2, paint); picture.endRecording(); SkBitmap store; store.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); store.allocPixels(); // Test parts of top-left tile { SkDevice device(store); MockCanvas mockCanvas(&device); picture.draw(&mockCanvas); REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]); } { SkDevice device(store); MockCanvas mockCanvas(&device); mockCanvas.translate(SkFloatToScalar(-7.99f), SkFloatToScalar(-7.99f)); picture.draw(&mockCanvas); REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]); } // Corner overlap { SkDevice device(store); MockCanvas mockCanvas(&device); mockCanvas.translate(SkFloatToScalar(-9.5f), SkFloatToScalar(-9.5f)); picture.draw(&mockCanvas); REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count()); REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]); REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]); } // Intersect bottom right tile, but does not overlap rect 2 { SkDevice device(store); MockCanvas mockCanvas(&device); mockCanvas.translate(SkFloatToScalar(-16.0f), SkFloatToScalar(-16.0f)); picture.draw(&mockCanvas); REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count()); REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]); } }
bool SkBlurImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const SkMatrix& ctm, SkBitmap* dst, SkIPoint* offset) { SkBitmap src = this->getInputResult(proxy, source, ctm, offset); if (src.config() != SkBitmap::kARGB_8888_Config) { return false; } SkAutoLockPixels alp(src); if (!src.getPixels()) { return false; } dst->setConfig(src.config(), src.width(), src.height()); dst->allocPixels(); int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX); getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY); if (kernelSizeX < 0 || kernelSizeY < 0) { return false; } if (kernelSizeX == 0 && kernelSizeY == 0) { src.copyTo(dst, dst->config()); return true; } SkBitmap temp; temp.setConfig(dst->config(), dst->width(), dst->height()); if (!temp.allocPixels()) { return false; } if (kernelSizeX > 0 && kernelSizeY > 0) { boxBlurX(src, &temp, kernelSizeX, lowOffsetX, highOffsetX); boxBlurY(temp, dst, kernelSizeY, lowOffsetY, highOffsetY); boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX); boxBlurY(temp, dst, kernelSizeY, highOffsetY, lowOffsetY); boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX); boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY); } else if (kernelSizeX > 0) { boxBlurX(src, dst, kernelSizeX, lowOffsetX, highOffsetX); boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX); boxBlurX(temp, dst, kernelSizeX3, highOffsetX, highOffsetX); } else if (kernelSizeY > 0) { boxBlurY(src, dst, kernelSizeY, lowOffsetY, highOffsetY); boxBlurY(*dst, &temp, kernelSizeY, highOffsetY, lowOffsetY); boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY); } return true; }
GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); bitmap.allocPixels(); bitmap.eraseColor(0); PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas(bitmap), true); GraphicsContext* ctx = new GraphicsContext(pgc); return ctx; }
static void TestDeferredCanvasBitmapSizeThreshold(skiatest::Reporter* reporter) { SkBitmap store; store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); store.allocPixels(); SkBitmap sourceImage; // 100 by 100 image, takes 40,000 bytes in memory sourceImage.setConfig(SkBitmap::kARGB_8888_Config, 100, 100); sourceImage.allocPixels(); // 1 under : should not store the image { SkDevice device(store); SkDeferredCanvas canvas(&device); canvas.setBitmapSizeThreshold(39999); canvas.drawBitmap(sourceImage, 0, 0, NULL); size_t newBytesAllocated = canvas.storageAllocatedForRecording(); REPORTER_ASSERT(reporter, newBytesAllocated == 0); } // exact value : should store the image { SkDevice device(store); SkDeferredCanvas canvas(&device); canvas.setBitmapSizeThreshold(40000); canvas.drawBitmap(sourceImage, 0, 0, NULL); size_t newBytesAllocated = canvas.storageAllocatedForRecording(); REPORTER_ASSERT(reporter, newBytesAllocated > 0); } // 1 over : should still store the image { SkDevice device(store); SkDeferredCanvas canvas(&device); canvas.setBitmapSizeThreshold(40001); canvas.drawBitmap(sourceImage, 0, 0, NULL); size_t newBytesAllocated = canvas.storageAllocatedForRecording(); REPORTER_ASSERT(reporter, newBytesAllocated > 0); } }
void drawBG(SkCanvas* canvas) { canvas->drawColor(0xFFDDDDDD); return; #if 0 SkColorTable ct; SkPMColor colors[] = { SK_ColorRED, SK_ColorBLUE }; ct.setColors(colors, 2); ct.setFlags(ct.getFlags() | SkColorTable::kColorsAreOpaque_Flag); SkBitmap bm; bm.setConfig(SkBitmap::kIndex8_Config, 20, 20, 21); bm.setColorTable(&ct); bm.allocPixels(); sk_memset16((uint16_t*)bm.getAddr8(0, 0), 0x0001, bm.rowBytes() * bm.height() / 2); #endif #if 0 SkBitmap bm; bm.setConfig(SkBitmap::kRGB_565_Config, 20, 20, 42); bm.allocPixels(); sk_memset32((uint32_t*)bm.getAddr16(0, 0), 0x0000FFFF, bm.rowBytes() * bm.height() / 4); #endif #if 1 SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20); bm.allocPixels(); sk_memset32((uint32_t*)bm.getAddr32(0, 0), 0xFFDDDDDD, bm.rowBytes() * bm.height() / 4); #endif SkPaint paint; // SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kBilinear_FilterType, SkShader::kRepeat_TileMode); SkPoint pts[] = { 0, 0, SkIntToScalar(100), SkIntToScalar(0) }; SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; SkShader* shader = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kMirror_TileMode); paint.setShader(shader)->unref(); canvas->drawPaint(paint); }
// This tests that GrTextureStripAtlas flushes pending IO on the texture it acquires. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureStripAtlasFlush, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); GrSurfaceDesc desc; desc.fWidth = 32; desc.fHeight = 32; desc.fConfig = kRGBA_8888_GrPixelConfig; GrTexture* texture = context->textureProvider()->createTexture(desc, SkBudgeted::kYes, nullptr, 0); GrSurfaceDesc targetDesc = desc; targetDesc.fFlags = kRenderTarget_GrSurfaceFlag; GrTexture* target = context->textureProvider()->createTexture(targetDesc, SkBudgeted::kYes, nullptr, 0); SkAutoTMalloc<uint32_t> pixels(desc.fWidth * desc.fHeight); memset(pixels.get(), 0xFF, sizeof(uint32_t) * desc.fWidth * desc.fHeight); texture->writePixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig, pixels.get()); // Add a pending read to the texture, and then make it available for reuse. context->copySurface(target, texture); texture->unref(); // Create an atlas with parameters that allow it to reuse the texture. GrTextureStripAtlas::Desc atlasDesc; atlasDesc.fContext = context; atlasDesc.fConfig = desc.fConfig; atlasDesc.fWidth = desc.fWidth; atlasDesc.fHeight = desc.fHeight; atlasDesc.fRowHeight = 1; GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(atlasDesc); // Write to the atlas' texture. SkImageInfo info = SkImageInfo::MakeN32(desc.fWidth, desc.fHeight, kPremul_SkAlphaType); size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig); SkBitmap bitmap; bitmap.allocPixels(info, rowBytes); memset(bitmap.getPixels(), 1, rowBytes * desc.fHeight); int row = atlas->lockRow(bitmap); if (!context->caps()->preferVRAMUseOverFlushes()) REPORTER_ASSERT(reporter, texture == atlas->getTexture()); // The atlas' use of its texture shouldn't change which pixels got copied to the target. SkAutoTMalloc<uint32_t> actualPixels(desc.fWidth * desc.fHeight); bool success = target->readPixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig, actualPixels.get()); REPORTER_ASSERT(reporter, success); REPORTER_ASSERT(reporter, !memcmp(pixels.get(), actualPixels.get(), sizeof(uint32_t) * desc.fWidth * desc.fHeight)); target->unref(); atlas->unlockRow(row); }
static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info, const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* digest, const SkMD5::Digest* goodDigest) { REPORTER_ASSERT(r, info.dimensions() == size); bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); REPORTER_ASSERT(r, result == expectedResult); md5(bm, digest); if (goodDigest) { REPORTER_ASSERT(r, *digest == *goodDigest); } { // Test decoding to 565 SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); SkCodec::Result expected565 = info.alphaType() == kOpaque_SkAlphaType ? expectedResult : SkCodec::kInvalidConversion; test_info(r, codec, info565, expected565, nullptr); } // Verify that re-decoding gives the same result. It is interesting to check this after // a decode to 565, since choosing to decode to 565 may result in some of the decode // options being modified. These options should return to their defaults on another // decode to kN32, so the new digest should match the old digest. test_info(r, codec, info, expectedResult, digest); { // Check alpha type conversions if (info.alphaType() == kOpaque_SkAlphaType) { test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType), expectedResult, digest); test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType), expectedResult, digest); } else { // Decoding to opaque should fail test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType), SkCodec::kInvalidConversion, nullptr); SkAlphaType otherAt = info.alphaType(); if (kPremul_SkAlphaType == otherAt) { otherAt = kUnpremul_SkAlphaType; } else { otherAt = kPremul_SkAlphaType; } // The other non-opaque alpha type should always succeed, but not match. test_info(r, codec, info.makeAlphaType(otherAt), expectedResult, nullptr); } } }
bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) { size_t size = pdf->getLength(); SkAutoFree buffer(sk_malloc_throw(size)); pdf->read(buffer.get(), size); SkAutoTDelete<poppler::document> doc( poppler::document::load_from_raw_data((const char*)buffer.get(), size)); if (!doc.get() || doc->is_locked()) { return false; } SkAutoTDelete<poppler::page> page(doc->create_page(0)); poppler::page_renderer renderer; poppler::image image = renderer.render_page(page.get()); if (!image.is_valid() || image.format() != poppler::image::format_argb32) { return false; } int width = image.width(), height = image.height(); size_t rowSize = image.bytes_per_row(); char *imgData = image.data(); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); if (!bitmap.allocPixels()) { return false; } bitmap.eraseColor(SK_ColorWHITE); SkPMColor* bitmapPixels = (SkPMColor*)bitmap.getPixels(); // do pixel-by-pixel copy to deal with RGBA ordering conversions for (int y = 0; y < height; y++) { char *rowData = imgData; for (int x = 0; x < width; x++) { uint8_t a = rowData[3]; uint8_t r = rowData[2]; uint8_t g = rowData[1]; uint8_t b = rowData[0]; *bitmapPixels = SkPreMultiplyARGB(a, r, g, b); bitmapPixels++; rowData += 4; } imgData += rowSize; } output->swap(bitmap); return true; }
bool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) { if (!drawPaths) { return true; } if (gShowAsciiPaths) { showPath(one, "one:"); showPath(two, "two:"); } const SkRect& bounds1 = one.getBounds(); const SkRect& bounds2 = two.getBounds(); SkRect larger = bounds1; larger.join(bounds2); SkBitmap bits; char out[256]; int bitWidth = SkScalarCeil(larger.width()) + 2; if (bitWidth * 2 + 1 >= (int) sizeof(out)) { return false; } int bitHeight = SkScalarCeil(larger.height()) + 2; if (bitHeight >= (int) sizeof(out)) { return false; } bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight); bits.allocPixels(); SkCanvas canvas(bits); canvas.drawColor(SK_ColorWHITE); SkPaint paint; canvas.save(); canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); canvas.drawPath(one, paint); canvas.restore(); canvas.save(); canvas.translate(-bounds2.fLeft + 1 + bitWidth, -bounds2.fTop + 1); canvas.drawPath(two, paint); canvas.restore(); for (int y = 0; y < bitHeight; ++y) { uint32_t* addr1 = bits.getAddr32(0, y); int x; char* outPtr = out; for (x = 0; x < bitWidth; ++x) { *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; } *outPtr++ = '|'; for (x = bitWidth; x < bitWidth * 2; ++x) { *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; } *outPtr++ = '\0'; SkDebugf("%s\n", out); } return true; }
DEF_TEST(Picture_EncodedData, reporter) { // Create a bitmap that will be encoded. SkBitmap original; make_bm(&original, 100, 100, SK_ColorBLUE, true); SkDynamicMemoryWStream wStream; if (!SkImageEncoder::EncodeStream(&wStream, original, SkImageEncoder::kPNG_Type, 100)) { return; } SkAutoDataUnref data(wStream.copyToData()); SkBitmap bm; bool installSuccess = SkDEPRECATED_InstallDiscardablePixelRef(data, &bm); REPORTER_ASSERT(reporter, installSuccess); // Write both bitmaps to pictures, and ensure that the resulting data streams are the same. // Flattening original will follow the old path of performing an encode, while flattening bm // will use the already encoded data. SkAutoDataUnref picture1(serialized_picture_from_bitmap(original)); SkAutoDataUnref picture2(serialized_picture_from_bitmap(bm)); REPORTER_ASSERT(reporter, picture1->equals(picture2)); // Now test that a parse error was generated when trying to create a new SkPicture without // providing a function to decode the bitmap. ErrorContext context; context.fErrors = 0; context.fReporter = reporter; SkSetErrorCallback(assert_one_parse_error_cb, &context); SkMemoryStream pictureStream(picture1); SkClearLastError(); sk_sp<SkPicture> pictureFromStream(SkPicture::MakeFromStream(&pictureStream, nullptr)); REPORTER_ASSERT(reporter, pictureFromStream.get() != nullptr); SkClearLastError(); SkSetErrorCallback(nullptr, nullptr); // Test that using the version of CreateFromStream that just takes a stream also decodes the // bitmap. Drawing this picture should look exactly like the original bitmap. SkMD5::Digest referenceDigest; md5(original, &referenceDigest); SkBitmap dst; dst.allocPixels(original.info()); dst.eraseColor(SK_ColorRED); SkCanvas canvas(dst); pictureStream.rewind(); pictureFromStream = SkPicture::MakeFromStream(&pictureStream); canvas.drawPicture(pictureFromStream.get()); SkMD5::Digest digest2; md5(dst, &digest2); REPORTER_ASSERT(reporter, referenceDigest == digest2); }
static void test_info(skiatest::Reporter* r, Codec* codec, const SkImageInfo& info, SkCodec::Result expectedResult, const SkMD5::Digest* goodDigest) { SkBitmap bm; bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); REPORTER_ASSERT(r, result == expectedResult); if (goodDigest) { compare_to_good_digest(r, *goodDigest, bm); } }
static SkBitmap createBitmapWithSpace(const SkBitmap& bitmap, int spaceWidth, int spaceHeight) { SkBitmap result; result.setConfig(bitmap.config(), bitmap.width() + spaceWidth, bitmap.height() + spaceHeight); result.allocPixels(); result.eraseColor(SK_ColorTRANSPARENT); bitmap.copyPixelsTo(reinterpret_cast<uint8_t*>(result.getPixels()), result.rowBytes() * result.height(), result.rowBytes()); return result; }
void onOnceBeforeDraw() override { this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) ); fRect.set(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(30), SkIntToScalar(30)); fBitmap.allocPixels(SkImageInfo::Make(20, 20, SkColorType::kAlpha_8_SkColorType, kPremul_SkAlphaType)); SkCanvas canvas(fBitmap); canvas.clear(0x0); SkPaint p; canvas.drawRect(SkRect::MakeXYWH(10, 0, 10, 10), p); canvas.drawRect(SkRect::MakeXYWH(0, 10, 10, 10), p); }
void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height) { SkBitmap rgbaBitmap; rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0, bitmap->alphaType()); rgbaBitmap.allocPixels(); rgbaBitmap.eraseColor(0); SkCanvas canvas(rgbaBitmap); canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL); uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels()); }
static SkBitmap* create_bitmap() { SkBitmap* bm = SkNEW(SkBitmap); // Use a large bitmap. const int W = 1000, H = 1000; bm->setConfig(SkBitmap::kARGB_8888_Config, W, H); bm->allocPixels(); bm->eraseColor(SK_ColorBLACK); SkCanvas canvas(*bm); SkPaint paint; paint.setColor(SK_ColorBLUE); canvas.drawRectCoords(0, 0, SkIntToScalar(W/2), SkIntToScalar(H/2), paint); return bm; }
// https://bug.skia.org/4390 DEF_TEST(ImageFromIndex8Bitmap, r) { SkPMColor pmColors[1] = {SkPreMultiplyColor(SK_ColorWHITE)}; SkBitmap bm; SkAutoTUnref<SkColorTable> ctable( new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors))); SkImageInfo info = SkImageInfo::Make(1, 1, kIndex_8_SkColorType, kPremul_SkAlphaType); bm.allocPixels(info, nullptr, ctable); SkAutoLockPixels autoLockPixels(bm); *bm.getAddr8(0, 0) = 0; SkAutoTUnref<SkImage> img(SkImage::NewFromBitmap(bm)); REPORTER_ASSERT(r, img.get() != nullptr); }
// Currently the supersampler blitter uses int16_t for its index into an array // the width of the clip. Test that we don't crash/assert if we try to draw // with a device/clip that is larger. static void test_giantClip() { SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 64919, 1); bm.allocPixels(); SkCanvas canvas(bm); canvas.clear(SK_ColorTRANSPARENT); SkPath path; path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(33, 1); SkPaint paint; paint.setAntiAlias(true); canvas.drawPath(path, paint); }
// This used to assert in debug builds (and crash writing bad memory in release) // because we overflowed an intermediate value (B coefficient) setting up our // stepper for the quadratic. Now we bias that value by 1/2 so we don't overflow static void test_crbug_140803(skiatest::Reporter* reporter) { SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 2700, 30*1024); bm.allocPixels(); SkCanvas canvas(bm); SkPath path; path.moveTo(2762, 20); path.quadTo(11, 21702, 10, 21706); SkPaint paint; paint.setAntiAlias(true); canvas.drawPath(path, paint); }
bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) { size_t size = stream->getLength(); void* ptr = sk_malloc_throw(size); stream->read(ptr, size); CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size, CGDataProviderReleaseData_FromMalloc); if (NULL == data) { return false; } CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data); CGDataProviderRelease(data); if (NULL == pdf) { return false; } SkAutoPDFRelease releaseMe(pdf); CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1); if (NULL == page) { return false; } CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); int w = (int)CGRectGetWidth(bounds); int h = (int)CGRectGetHeight(bounds); SkBitmap bitmap; if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) { return false; } bitmap.eraseColor(SK_ColorWHITE); size_t bitsPerComponent; CGBitmapInfo info; getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL); CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h, bitsPerComponent, bitmap.rowBytes(), cs, info); CGColorSpaceRelease(cs); if (ctx) { CGContextDrawPDFPage(ctx, page); CGContextRelease(ctx); } output->swap(bitmap); return true; }