Example #1
0
    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);
    }
Example #2
0
    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);
}
Example #4
0
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;
}
Example #6
0
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);
}
Example #10
0
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());
}
Example #12
0
    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]);
        }
    }
Example #13
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;
}
Example #15
0
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);
    }
Example #17
0
// 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);
}
Example #18
0
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;
}
Example #20
0
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;
}
Example #21
0
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);
}
Example #22
0
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;
}
Example #24
0
 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;
}
Example #27
0
// 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);
}
Example #29
0
// 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;
}