/**
 *  Test that for Jpeg files that use the JFIF colorspace, they are
 *  directly embedded into the PDF (without re-encoding) when that
 *  makes sense.
 */
DEF_TEST(PDFJpegEmbedTest, r) {
    const char test[] = "PDFJpegEmbedTest";
    SkAutoTUnref<SkData> mandrillData(
            load_resource(r, test, "mandrill_512_q075.jpg"));
    SkAutoTUnref<SkData> cmykData(load_resource(r, test, "CMYK.jpg"));
    if (!mandrillData || !cmykData) {
        return;
    }
    ////////////////////////////////////////////////////////////////////////////
    SkDynamicMemoryWStream pdf;
    SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdf));
    SkCanvas* canvas = document->beginPage(642, 1028);

    canvas->clear(SK_ColorLTGRAY);

    SkBitmap bm1(bitmap_from_data(mandrillData));
    canvas->drawBitmap(bm1, 65.0, 0.0, nullptr);
    SkBitmap bm2(bitmap_from_data(cmykData));
    canvas->drawBitmap(bm2, 0.0, 512.0, nullptr);

    canvas->flush();
    document->endPage();
    document->close();
    SkAutoTUnref<SkData> pdfData(pdf.copyToData());
    SkASSERT(pdfData);
    pdf.reset();

    REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData));

    // This JPEG uses a nonstandard colorspace - it can not be
    // embedded into the PDF directly.
    REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData));
    ////////////////////////////////////////////////////////////////////////////
    pdf.reset();
    document.reset(SkDocument::CreatePDF(&pdf));
    canvas = document->beginPage(642, 1028);

    canvas->clear(SK_ColorLTGRAY);

    SkAutoTUnref<SkImage> im1(SkImage::NewFromEncoded(mandrillData));
    canvas->drawImage(im1, 65.0, 0.0, nullptr);
    SkAutoTUnref<SkImage> im2(SkImage::NewFromEncoded(cmykData));
    canvas->drawImage(im2, 0.0, 512.0, nullptr);

    canvas->flush();
    document->endPage();
    document->close();
    pdfData.reset(pdf.copyToData());
    SkASSERT(pdfData);
    pdf.reset();

    REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData));

    // This JPEG uses a nonstandard colorspace - it can not be
    // embedded into the PDF directly.
    REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData));
}
Beispiel #2
0
static SkImage* create_picture_image() {
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(10, 10);
    canvas->clear(SK_ColorCYAN);
    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
};
static void render_picture(GrContext* grContext,
                           int width,
                           int height,
                           const SkPicture* picture,
                           const SkMatrix& matrix) {
    SkASSERT(grContext);
    if (!picture) {
        SkDebugf(TAG "!picture\n");
        return;
    }
    // Render to the default framebuffer render target.
    GrBackendRenderTargetDesc desc;
    desc.fWidth = width;
    desc.fHeight = height;
    desc.fConfig = kSkia8888_GrPixelConfig;
    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    SkSurfaceProps surfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
                                kUnknown_SkPixelGeometry);
    // TODO:  Check to see if we can keep the surface between draw calls.
    SkAutoTUnref<SkSurface> surface(
            SkSurface::NewFromBackendRenderTarget(
                    grContext, desc, &surfaceProps));
    if (surface) {
        SkCanvas* canvas = surface->getCanvas();
        SkASSERT(canvas);
        canvas->clear(SK_ColorGRAY);
        canvas->concat(matrix);
        SkRect cullRect = picture->cullRect();
        canvas->clipRect(cullRect);
        picture->playback(canvas);
        canvas->flush();
    }
}
 void onDraw(SkCanvas* canvas) override {
     SkPaint blurPaint;
     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(5.0f, 5.0f));
     blurPaint.setImageFilter(blur);
     const SkScalar tile_size = SkIntToScalar(128);
     SkRect bounds;
     if (!canvas->getClipBounds(&bounds)) {
         bounds.setEmpty();
     }
     int ts = SkScalarCeilToInt(tile_size);
     SkImageInfo info = SkImageInfo::MakeN32Premul(ts, ts);
     SkAutoTUnref<SkSurface> tileSurface(canvas->newSurface(info));
     if (!tileSurface.get()) {
         tileSurface.reset(SkSurface::NewRaster(info));
     }
     SkCanvas* tileCanvas = tileSurface->getCanvas();
     for (SkScalar y = bounds.top(); y < bounds.bottom(); y += tile_size) {
         for (SkScalar x = bounds.left(); x < bounds.right(); x += tile_size) {
             tileCanvas->save();
             tileCanvas->clear(0);
             tileCanvas->translate(-x, -y);
             SkRect rect = SkRect::MakeWH(WIDTH, HEIGHT);
             tileCanvas->saveLayer(&rect, &blurPaint);
             SkRRect rrect = SkRRect::MakeRectXY(rect.makeInset(20, 20), 25, 25);
             tileCanvas->clipRRect(rrect, SkRegion::kDifference_Op, true);
             SkPaint paint;
             tileCanvas->drawRect(rect, paint);
             tileCanvas->restore();
             tileCanvas->restore();
             canvas->drawImage(tileSurface->makeImageSnapshot().get(), x, y);
         }
     }
 }
Beispiel #5
0
// Verify that associated bitmap cache entries are purged on SkImage destruction.
DEF_TEST(BitmapCache_discarded_image, reporter) {
    // Cache entries associated with SkImages fall into two categories:
    //
    // 1) generated image bitmaps (managed by the image cacherator)
    // 2) scaled/resampled bitmaps (cached when HQ filters are used)
    //
    // To exercise the first cache type, we use generated/picture-backed SkImages.
    // To exercise the latter, we draw scaled bitmap images using HQ filters.

    const SkMatrix xforms[] = {
        SkMatrix::MakeScale(1, 1),
        SkMatrix::MakeScale(1.7f, 0.5f),
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(xforms); ++i) {
        test_discarded_image(reporter, xforms[i], []() {
            auto surface(SkSurface::MakeRasterN32Premul(10, 10));
            surface->getCanvas()->clear(SK_ColorCYAN);
            return surface->makeImageSnapshot();
        });

        test_discarded_image(reporter, xforms[i], []() {
            SkPictureRecorder recorder;
            SkCanvas* canvas = recorder.beginRecording(10, 10);
            canvas->clear(SK_ColorCYAN);
            return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
                                            SkISize::Make(10, 10), nullptr, nullptr,
                                            SkImage::BitDepth::kU8,
                                            SkColorSpace::MakeSRGB());
        });
    }
}
Beispiel #6
0
int main(int, char**) {
    bool gl_ok = setup_gl_context();
    srand(time(nullptr));
    std::shared_ptr<SkSurface> surface = (gl_ok && rand() % 2) ? create_opengl_surface(320, 240)
                                                               : create_raster_surface(320, 240);

    // Create a left-to-right green-to-purple gradient shader.
    SkPoint pts[] = { {0,0}, {320,240} };
    SkColor colors[] = { 0xFF00FF00, 0xFFFF00FF };
    // Our text will draw with this paint: size 24, antialiased, with the shader.
    SkPaint paint;
    paint.setTextSize(24);
    paint.setAntiAlias(true);
    paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kRepeat_TileMode));

    // Draw to the surface via its SkCanvas.
    SkCanvas* canvas = surface->getCanvas();   // We don't manage this pointer's lifetime.
    static const char* msg = "Hello world!";
    canvas->clear(SK_ColorWHITE);
    canvas->drawText(msg, strlen(msg), 90,120, paint);

    // Grab a snapshot of the surface as an immutable SkImage.
    std::shared_ptr<SkImage> image = adopt(surface->newImageSnapshot());
    // Encode that image as a .png into a blob in memory.
    std::shared_ptr<SkData> png = adopt(image->encode(SkImageEncoder::kPNG_Type, 100));

    // This code is no longer Skia-specific.  We just dump the .png to disk.  Any way works.
    static const char* path = "example.png";
    std::ofstream(path, std::ios::out | std::ios::binary)
        .write((const char*)png->data(), png->size());
    std::cout << "Wrote " << path << std::endl;

    return 0;
}
static sk_sp<SkImage> create_gpu_image(GrContext* grContext) {
    const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
    auto surface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorWHITE);
    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
    return surface->makeImageSnapshot();
}
Beispiel #8
0
// Creates a bitmap and a matching image.
static sk_sp<SkImage> makebm(SkCanvas* origCanvas, SkBitmap* resultBM, int w, int h) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);

    auto surface(sk_tool_utils::makeSurface(origCanvas, info));
    SkCanvas* canvas = surface->getCanvas();

    canvas->clear(SK_ColorTRANSPARENT);

    SkScalar wScalar = SkIntToScalar(w);
    SkScalar hScalar = SkIntToScalar(h);

    SkPoint     pt = { wScalar / 2, hScalar / 2 };

    SkScalar    radius = 4 * SkMaxScalar(wScalar, hScalar);

    SkColor     colors[] = { SK_ColorRED, SK_ColorYELLOW,
                             SK_ColorGREEN, SK_ColorMAGENTA,
                             SK_ColorBLUE, SK_ColorCYAN,
                             SK_ColorRED};

    SkScalar    pos[] = {0,
                         SK_Scalar1 / 6,
                         2 * SK_Scalar1 / 6,
                         3 * SK_Scalar1 / 6,
                         4 * SK_Scalar1 / 6,
                         5 * SK_Scalar1 / 6,
                         SK_Scalar1};

    SkPaint     paint;
    SkRect rect = SkRect::MakeWH(wScalar, hScalar);
    SkMatrix mat = SkMatrix::I();
    for (int i = 0; i < 4; ++i) {
        paint.setShader(SkGradientShader::MakeRadial(
                        pt, radius,
                        colors, pos,
                        SK_ARRAY_COUNT(colors),
                        SkShader::kRepeat_TileMode,
                        0, &mat));
        canvas->drawRect(rect, paint);
        rect.inset(wScalar / 8, hScalar / 8);
        mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4);
    }

    auto image = surface->makeImageSnapshot();

    SkBitmap tempBM;

    image->asLegacyBitmap(&tempBM);

    // Let backends know we won't change this, so they don't have to deep copy it defensively.
    tempBM.setImmutable();
    *resultBM = tempBM;

    return image;
}
Beispiel #9
0
// Test out the layer replacement functionality with and w/o a BBH
void test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace) {
    sk_sp<SkPicture> pic;

    {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
        SkPaint paint;
        canvas->saveLayer(nullptr, &paint);
        canvas->clear(SK_ColorRED);
        canvas->restore();
        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)),
                         SkPaint());
        pic = recorder.finishRecordingAsPicture();
    }

    SkAutoTUnref<GrTexture> texture;
    SkPaint paint;
    GrLayerCache* layerCache = context->getLayerCache();

    if (doReplace) {
        int key[1] = { 0 };

        GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2,
                                                             SkIRect::MakeWH(kWidth, kHeight),
                                                             SkIRect::MakeWH(kWidth, kHeight),
                                                             SkMatrix::I(), key, 1, &paint);

        GrSurfaceDesc desc;
        desc.fConfig = kSkia8888_GrPixelConfig;
        desc.fFlags = kRenderTarget_GrSurfaceFlag;
        desc.fWidth = kWidth;
        desc.fHeight = kHeight;
        desc.fSampleCnt = 0;

        // Giving the texture some initial data so the Gpu (specifically vulkan) does not complain
        // when reading from an uninitialized texture.
        SkAutoTMalloc<uint32_t> srcBuffer(kWidth*kHeight);
        memset(srcBuffer.get(), 0, kWidth*kHeight*sizeof(uint32_t));

        texture.reset(context->textureProvider()->createTexture(
                desc, SkBudgeted::kNo, srcBuffer.get(), 0));
        layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false);
    }

    SkRecord rerecord;
    SkRecorder canvas(&rerecord, kWidth, kHeight);
    GrRecordReplaceDraw(pic.get(), &canvas, layerCache, SkMatrix::I(), nullptr/*callback*/);

    int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord);
    if (doReplace) {
        REPORTER_ASSERT(r, 0 == numLayers);
    } else {
        REPORTER_ASSERT(r, 1 == numLayers);
    }
}
Beispiel #10
0
SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
    SkCanvas* canvas;
    switch(fDeviceType) {
        case kBitmap_DeviceType: {
            SkBitmap bitmap;
            sk_tools::setup_bitmap(&bitmap, width, height);
            canvas = SkNEW_ARGS(SkCanvas, (bitmap));
        }
        break;
#if SK_SUPPORT_GPU
#if SK_ANGLE
        case kAngle_DeviceType:
            // fall through
#endif
#if SK_MESA
        case kMesa_DeviceType:
            // fall through
#endif
        case kGPU_DeviceType:
        case kNVPR_DeviceType: {
            SkAutoTUnref<GrSurface> target;
            if (fGrContext) {
                // create a render target to back the device
                GrTextureDesc desc;
                desc.fConfig = kSkia8888_GrPixelConfig;
                desc.fFlags = kRenderTarget_GrTextureFlagBit;
                desc.fWidth = width;
                desc.fHeight = height;
                desc.fSampleCnt = fSampleCount;
                target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
            }
            if (NULL == target.get()) {
                SkASSERT(0);
                return NULL;
            }

            SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target));
            canvas = SkNEW_ARGS(SkCanvas, (device.get()));
            break;
        }
#endif
        default:
            SkASSERT(0);
            return NULL;
    }
    setUpFilter(canvas, fDrawFilters);
    this->scaleToScaleFactor(canvas);

    // Pictures often lie about their extent (i.e., claim to be 100x100 but
    // only ever draw to 90x100). Clear here so the undrawn portion will have
    // a consistent color
    canvas->clear(SK_ColorTRANSPARENT);
    return canvas;
}
Beispiel #11
0
 void makePicture() {
     SkCanvas* canvas = fPicture.beginRecording(100, 100);
     canvas->clear(0x00000000);
     SkPaint paint;
     paint.setAntiAlias(true);
     paint.setColor(0xFFFFFFFF);
     paint.setTextSize(SkIntToScalar(96));
     const char* str = "e";
     canvas->drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
     fPicture.endRecording();
 }
sk_sp<SkSpecialImage> SkDropShadowImageFilter::onFilterImage(SkSpecialImage* source,
                                                             const Context& ctx,
                                                             SkIPoint* offset) const {
    SkIPoint inputOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
    if (!input) {
        return nullptr;
    }

    const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
                                                  input->width(), input->height());
    SkIRect bounds;
    if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
        return nullptr;
    }

    const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
                                                  kPremul_SkAlphaType);
    sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    canvas->clear(0x0);

    SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
    ctx.ctm().mapVectors(&sigma, 1);
    sigma.fX = SkMaxScalar(0, sigma.fX);
    sigma.fY = SkMaxScalar(0, sigma.fY);

    SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY));
    SkPaint paint;
    paint.setImageFilter(blurFilter.get());
    paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkXfermode::kSrcIn_Mode));
    paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);

    SkVector offsetVec = SkVector::Make(fDx, fDy);
    ctx.ctm().mapVectors(&offsetVec, 1);

    canvas->translate(SkIntToScalar(inputOffset.fX - bounds.fLeft),
                      SkIntToScalar(inputOffset.fY - bounds.fTop));
    input->draw(canvas, offsetVec.fX, offsetVec.fY, &paint);

    if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
        input->draw(canvas, 0, 0, nullptr);
    }
    offset->fX = bounds.fLeft;
    offset->fY = bounds.fTop;
    return surf->makeImageSnapshot();
}
Beispiel #13
0
sk_sp<SkSpecialImage> SkImageSource::onFilterImage(SkSpecialImage* source, const Context& ctx,
                                                   SkIPoint* offset) const {
    SkRect dstRect;
    ctx.ctm().mapRect(&dstRect, fDstRect);

    SkRect bounds = SkRect::MakeIWH(fImage->width(), fImage->height());
    if (fSrcRect == bounds) {
        int iLeft = dstRect.fLeft;
        int iTop = dstRect.fTop;
        // TODO: this seems to be a very noise-prone way to determine this (esp. the floating-point
        // widths & heights).
        if (dstRect.width() == bounds.width() && dstRect.height() == bounds.height() &&
            iLeft == dstRect.fLeft && iTop == dstRect.fTop) {
            // The dest is just an un-scaled integer translation of the entire image; return it
            offset->fX = iLeft;
            offset->fY = iTop;

            return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(fImage->width(), fImage->height()),
                                                 fImage, ctx.outputProperties().colorSpace(),
                                                 &source->props());
        }
    }

    const SkIRect dstIRect = dstRect.roundOut();

    sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), dstIRect.size()));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    // TODO: it seems like this clear shouldn't be necessary (see skbug.com/5075)
    canvas->clear(0x0);

    SkPaint paint;

    // Subtract off the integer component of the translation (will be applied in offset, below).
    dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop));
    paint.setBlendMode(SkBlendMode::kSrc);
    // FIXME: this probably shouldn't be necessary, but drawImageRect asserts
    // None filtering when it's translate-only
    paint.setFilterQuality(
        fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ?
               kNone_SkFilterQuality : fFilterQuality);
    canvas->drawImageRect(fImage.get(), fSrcRect, dstRect, &paint,
                          SkCanvas::kStrict_SrcRectConstraint);

    offset->fX = dstIRect.fLeft;
    offset->fY = dstIRect.fTop;
    return surf->makeImageSnapshot();
}
Beispiel #14
0
static SkImage* make_image(GrContext* ctx, int w, int h, const SkIRect& ir) {
    const SkImageInfo info = SkImageInfo::MakeN32(w, h, kOpaque_SkAlphaType);
    SkAutoTUnref<SkSurface> surface(ctx ?
                                    SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info) :
                                    SkSurface::NewRaster(info));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorWHITE);

    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    canvas->drawRect(SkRect::Make(ir), paint);
    return surface->newImageSnapshot();
}
Beispiel #15
0
static sk_sp<SkPicture> make_picture() {
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(100, 100, nullptr, 0);
    canvas->clear(SK_ColorBLACK);
    SkPaint paint;
    paint.setAntiAlias(true);
    sk_tool_utils::set_portable_typeface(&paint);
    paint.setColor(0xFFFFFFFF);
    paint.setTextSize(SkIntToScalar(96));
    const char* str = "e";
    canvas->drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
    return recorder.finishRecordingAsPicture();
}
static SkImage* create_circle_texture(int size, SkColor color) {
    SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(size, size));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(0xFF000000);

    SkPaint paint;
    paint.setColor(color);
    paint.setStrokeWidth(3);
    paint.setStyle(SkPaint::kStroke_Style);

    canvas->drawCircle(SkScalarHalf(size), SkScalarHalf(size), SkScalarHalf(size), paint);

    return surface->newImageSnapshot();
}
// Test out the layer replacement functionality with and w/o a BBH
void test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace) {
    SkAutoTUnref<const SkPicture> pic;

    {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
        SkPaint paint;
        canvas->saveLayer(nullptr, &paint);
        canvas->clear(SK_ColorRED);
        canvas->restore();
        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)),
                         SkPaint());
        pic.reset(recorder.endRecording());
    }

    SkAutoTUnref<GrTexture> texture;
    SkPaint paint;
    GrLayerCache* layerCache = context->getLayerCache();

    if (doReplace) {
        int key[1] = { 0 };

        GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2,
                                                             SkIRect::MakeWH(kWidth, kHeight),
                                                             SkIRect::MakeWH(kWidth, kHeight),
                                                             SkMatrix::I(), key, 1, &paint);

        GrSurfaceDesc desc;
        desc.fConfig = kSkia8888_GrPixelConfig;
        desc.fFlags = kRenderTarget_GrSurfaceFlag;
        desc.fWidth = kWidth;
        desc.fHeight = kHeight;
        desc.fSampleCnt = 0;

        texture.reset(context->textureProvider()->createTexture(
                desc, SkBudgeted::kNo, nullptr, 0));
        layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false);
    }

    SkRecord rerecord;
    SkRecorder canvas(&rerecord, kWidth, kHeight);
    GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), nullptr/*callback*/);

    int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord);
    if (doReplace) {
        REPORTER_ASSERT(r, 0 == numLayers);
    } else {
        REPORTER_ASSERT(r, 1 == numLayers);    
    }
}
SkSpecialImage* SkOffsetImageFilter::onFilterImage(SkSpecialImage* source,
                                                   const Context& ctx,
                                                   SkIPoint* offset) const {
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    SkAutoTUnref<SkSpecialImage> input(this->filterInput(0, source, ctx, &srcOffset));
    if (!input) {
        return nullptr;
    }

    SkVector vec;
    ctx.ctm().mapVectors(&vec, &fOffset, 1);

    if (!this->cropRectIsSet()) {
        offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
        offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
        return input.release();
    } else {
        SkIRect bounds;
        SkIRect srcBounds = SkIRect::MakeWH(input->width(), input->height());
        srcBounds.offset(srcOffset);
        if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
            return nullptr;
        }

        SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
                                                kPremul_SkAlphaType);
        sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
        if (!surf) {
            return nullptr;
        }

        SkCanvas* canvas = surf->getCanvas();
        SkASSERT(canvas);

        // TODO: it seems like this clear shouldn't be necessary (see skbug.com/5075)
        canvas->clear(0x0);

        SkPaint paint;
        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        canvas->translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
                          SkIntToScalar(srcOffset.fY - bounds.fTop));

        input->draw(canvas, vec.x(), vec.y(), &paint);

        offset->fX = bounds.fLeft;
        offset->fY = bounds.fTop;
        return surf->makeImageSnapshot().release();
    }
}
Beispiel #19
0
void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
                                       const SkTDArray<GrHoistedLayer>& atlased) {
    if (atlased.count() > 0) {
        // All the atlased layers are rendered into the same GrTexture
        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
                                        atlased[0].fLayer->texture()->asRenderTarget(), &props));

        SkCanvas* atlasCanvas = surface->getCanvas();

        for (int i = 0; i < atlased.count(); ++i) {
            const GrCachedLayer* layer = atlased[i].fLayer;
            const SkBigPicture* pict = atlased[i].fPicture->asSkBigPicture();
            if (!pict) {
                // TODO: can we assume / assert this?
                continue;
            }
            const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop);
            SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();)

            SkASSERT(!layerPaint || !layerPaint->getImageFilter());
            SkASSERT(!layer->filter());

            atlasCanvas->save();

            // Add a rect clip to make sure the rendering doesn't
            // extend beyond the boundaries of the atlased sub-rect
            const SkRect bound = SkRect::Make(layer->rect());
            atlasCanvas->clipRect(bound);
            atlasCanvas->clear(0);

            // '-offset' maps the layer's top/left to the origin.
            // Since this layer is atlased, the top/left corner needs
            // to be offset to the correct location in the backing texture.
            SkMatrix initialCTM;
            initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY));
            initialCTM.preTranslate(bound.fLeft, bound.fTop);
            initialCTM.preConcat(atlased[i].fPreMat);

            atlasCanvas->setMatrix(initialCTM);
            atlasCanvas->concat(atlased[i].fLocalMat);

            pict->partialPlayback(atlasCanvas, layer->start() + 1, layer->stop(), initialCTM);
            atlasCanvas->restore();
        }

        atlasCanvas->flush();
    }
Beispiel #20
0
static sk_sp<SkImage> make_gradient_circle(int width, int height) {
    SkScalar x = SkIntToScalar(width / 2);
    SkScalar y = SkIntToScalar(height / 2);
    SkScalar radius = SkMinScalar(x, y) * 0.8f;
    auto surface(SkSurface::MakeRasterN32Premul(width, height));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(0x00000000);
    SkColor colors[2];
    colors[0] = SK_ColorWHITE;
    colors[1] = SK_ColorBLACK;
    SkPaint paint;
    paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr,
        2, SkTileMode::kClamp));
    canvas->drawCircle(x, y, radius, paint);
    return surface->makeImageSnapshot();
}
Beispiel #21
0
sk_sp<SkSpecialImage> SkOffsetImageFilter::onFilterImage(SkSpecialImage* source,
                                                         const Context& ctx,
                                                         SkIPoint* offset) const {
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &srcOffset));
    if (!input) {
        return nullptr;
    }

    SkIPoint vec = map_offset_vector(ctx.ctm(), fOffset);

    if (!this->cropRectIsSet()) {
        offset->fX = Sk32_sat_add(srcOffset.fX, vec.fX);
        offset->fY = Sk32_sat_add(srcOffset.fY, vec.fY);
        return input;
    } else {
        SkIRect bounds;
        SkIRect srcBounds = SkIRect::MakeWH(input->width(), input->height());
        srcBounds.offset(srcOffset);
        if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
            return nullptr;
        }

        sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
        if (!surf) {
            return nullptr;
        }

        SkCanvas* canvas = surf->getCanvas();
        SkASSERT(canvas);

        // TODO: it seems like this clear shouldn't be necessary (see skbug.com/5075)
        canvas->clear(0x0);

        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);
        canvas->translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
                          SkIntToScalar(srcOffset.fY - bounds.fTop));

        input->draw(canvas, vec.fX, vec.fY, &paint);

        offset->fX = bounds.fLeft;
        offset->fY = bounds.fTop;
        return surf->makeImageSnapshot();
    }
}
Beispiel #22
0
// Return a larger (newWidth x newHeight) copy of 'src' with black padding
// around it.
static sk_sp<SkSpecialImage> pad_image(SkSpecialImage* src,
                                       int newWidth, int newHeight, int offX, int offY) {

    SkImageInfo info = SkImageInfo::MakeN32Premul(newWidth, newHeight);
    sk_sp<SkSpecialSurface> surf(src->makeSurface(info));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    canvas->clear(0x0);

    src->draw(canvas, offX, offY, nullptr);

    return surf->makeImageSnapshot();
}
Beispiel #23
0
void draw_child(skiatest::Reporter* reporter,
                const sk_gpu_test::ContextInfo& childInfo,
                const GrBackendTexture& backendTexture,
                const GrBackendSemaphore& semaphore) {

    childInfo.testContext()->makeCurrent();

    const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
                                                  kPremul_SkAlphaType);

    GrContext* childCtx = childInfo.grContext();
    sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childCtx, SkBudgeted::kNo,
                                                              childII, 0, kTopLeft_GrSurfaceOrigin,
                                                              nullptr));

    sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childCtx,
                                                         backendTexture,
                                                         kTopLeft_GrSurfaceOrigin,
                                                         kRGBA_8888_SkColorType,
                                                         kPremul_SkAlphaType,
                                                         nullptr,
                                                         nullptr,
                                                         nullptr);

    SkCanvas* childCanvas = childSurface->getCanvas();
    childCanvas->clear(SK_ColorRED);

    childSurface->wait(1, &semaphore);

    childCanvas->drawImage(childImage, CHILD_W/2, 0);

    SkPaint paint;
    paint.setColor(SK_ColorGREEN);
    SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
    childCanvas->drawIRect(rect, paint);

    // read pixels
    SkBitmap bitmap;
    bitmap.allocPixels(childII);
    childSurface->readPixels(bitmap, 0, 0);

    check_pixels(reporter, bitmap);
}
void draw(SkCanvas* ) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
    const size_t size = info.computeMinByteSize();
    SkAutoTMalloc<SkPMColor> storage(size);
    SkPMColor* pixels = storage.get();
    sk_sp<SkSurface> surface(SkSurface::MakeRasterDirect(info, pixels, info.minRowBytes()));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorWHITE);
    SkPMColor pmWhite = pixels[0];
    SkPaint paint;
    canvas->drawPoint(1, 1, paint);
    canvas->flush();  // ensure that point was drawn
    for (int y = 0; y < info.height(); ++y) {
        for (int x = 0; x < info.width(); ++x) {
            SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
        }
        SkDebugf("\n");
    }
}
Beispiel #25
0
/**
 *  Test that for Jpeg files that use the JFIF colorspace, they are
 *  directly embedded into the PDF (without re-encoding) when that
 *  makes sense.
 */
DEF_TEST(PDFJpegEmbedTest, r) {
    const char test[] = "PDFJpegEmbedTest";
    SkAutoTUnref<SkData> mandrillData(
            load_resource(r, test, "mandrill_512_q075.jpg"));
    SkAutoTUnref<SkData> cmykData(load_resource(r, test, "CMYK.jpg"));
    if (!mandrillData || !cmykData) {
        return;
    }

    SkDynamicMemoryWStream pdf;
    SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdf));
    SkCanvas* canvas = document->beginPage(642, 1028);

    canvas->clear(SK_ColorLTGRAY);

    SkBitmap bm1(bitmap_from_data(mandrillData));
    canvas->drawBitmap(bm1, 65.0, 0.0, NULL);
    SkBitmap bm2(bitmap_from_data(cmykData));
    canvas->drawBitmap(bm2, 0.0, 512.0, NULL);

    canvas->flush();
    document->endPage();
    document->close();
    SkAutoTUnref<SkData> pdfData(pdf.copyToData());
    SkASSERT(pdfData);
    pdf.reset();

    // Test disabled, waiting on resolution to http://skbug.com/3180
    // REPORTER_ASSERT(r, is_subset_of(mandrillData, pdfData));

    // This JPEG uses a nonstandard colorspace - it can not be
    // embedded into the PDF directly.
    REPORTER_ASSERT(r, !is_subset_of(cmykData, pdfData));

    // The following is for debugging purposes only.
    const char* outputPath = getenv("SKIA_TESTS_PDF_JPEG_EMBED_OUTPUT_PATH");
    if (outputPath) {
        SkFILEWStream output(outputPath);
        if (output.isValid()) {
            output.write(pdfData->data(), pdfData->size());
        }
    }
}
Beispiel #26
0
DEF_TEST(Picture_preserveCullRect, r) {
    SkPictureRecorder recorder;

    SkCanvas* c = recorder.beginRecording(SkRect::MakeLTRB(1, 2, 3, 4));
    c->clear(SK_ColorCYAN);

    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    SkDynamicMemoryWStream wstream;
    picture->serialize(&wstream);

    SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
    sk_sp<SkPicture> deserializedPicture(SkPicture::MakeFromStream(rstream));

    REPORTER_ASSERT(r, deserializedPicture != nullptr);
    REPORTER_ASSERT(r, deserializedPicture->cullRect().left() == 1);
    REPORTER_ASSERT(r, deserializedPicture->cullRect().top() == 2);
    REPORTER_ASSERT(r, deserializedPicture->cullRect().right() == 3);
    REPORTER_ASSERT(r, deserializedPicture->cullRect().bottom() == 4);
}
Beispiel #27
0
static sk_sp<SkImage> make_img() {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(WIDTH_HEIGHT, WIDTH_HEIGHT);

    sk_sp<SkSurface> surf(SkSurface::MakeRaster(info));

    SkCanvas* canvas = surf->getCanvas();

    canvas->clear(0x0);

    SkPaint paint;
    paint.setColor(SK_ColorBLUE);

    for (float pos = 0; pos < WIDTH_HEIGHT; pos += 16) {
        canvas->drawLine(0, pos, SkIntToScalar(WIDTH_HEIGHT), pos, paint);
        canvas->drawLine(pos, 0, pos, SkIntToScalar(WIDTH_HEIGHT), paint);
    }

    return surf->makeImageSnapshot();
}
sk_sp<SkSpecialImage> SkColorFilterImageFilter::onFilterImage(SkSpecialImage* source,
                                                              const Context& ctx,
                                                              SkIPoint* offset) const {
    SkIPoint inputOffset = SkIPoint::Make(0, 0);
    sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
    if (!input) {
        return nullptr;
    }

    SkIRect bounds;
    const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.fX, inputOffset.fY,
                                                  input->width(), input->height());
    if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
        return nullptr;
    }

    SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), kPremul_SkAlphaType);
    sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
    if (!surf) {
        return nullptr;
    }

    SkCanvas* canvas = surf->getCanvas();
    SkASSERT(canvas);

    // TODO: it seems like this clear shouldn't be necessary (see skbug.com/5075)
    canvas->clear(0x0);

    SkPaint paint;

    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    paint.setColorFilter(fColorFilter);

    input->draw(canvas,
                SkIntToScalar(inputOffset.fX - bounds.fLeft),
                SkIntToScalar(inputOffset.fY - bounds.fTop),
                &paint);

    offset->fX = bounds.fLeft;
    offset->fY = bounds.fTop;
    return surf->makeImageSnapshot();
}
    static sk_sp<SkImage> MakeAtlas(SkCanvas* caller, const SkRect& target) {
        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
        auto surface(sk_tool_utils::makeSurface(caller, info));
        SkCanvas* canvas = surface->getCanvas();
        // draw red everywhere, but we don't expect to see it in the draw, testing the notion
        // that drawAtlas draws a subset-region of the atlas.
        canvas->clear(SK_ColorRED);

        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kClear);
        SkRect r(target);
        r.inset(-1, -1);
        // zero out a place (with a 1-pixel border) to land our drawing.
        canvas->drawRect(r, paint);
        paint.setBlendMode(SkBlendMode::kSrcOver);
        paint.setColor(SK_ColorBLUE);
        paint.setAntiAlias(true);
        canvas->drawOval(target, paint);
        return surface->makeImageSnapshot();
    }
Beispiel #30
0
static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) {
    SkDevice* dev;
    SkCanvas canvas;

    const int kFixed = 28;
    const int kStretchy = 8;
    const int kSize = 2*kFixed + kStretchy;

#if SK_SUPPORT_GPU
    if (ctx) {
        dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize);
        *bitmap = dev->accessBitmap(false);
    } else
#endif
    {
        bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
        bitmap->allocPixels();
        dev = new SkDevice(*bitmap);
    }

    canvas.setDevice(dev)->unref();
    canvas.clear(0);

    SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
    const SkScalar strokeWidth = SkIntToScalar(6);
    const SkScalar radius = SkIntToScalar(kFixed) - strokeWidth/2;

    center->setXYWH(kFixed, kFixed, kStretchy, kStretchy);

    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(0xFFFF0000);
    canvas.drawRoundRect(r, radius, radius, paint);
    r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize));
    paint.setColor(0x8800FF00);
    canvas.drawRect(r, paint);
    r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy));
    paint.setColor(0x880000FF);
    canvas.drawRect(r, paint);
}