blob: d5511442ef7e6c3ab0d149379e31fa0fb449811c [file] [log] [blame]
#Topic Surface
#Alias Surface_Reference ##
#Class SkSurface
#Code
#Populate
##
SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be
allocated either in CPU memory, if a raster surface; or on the GPU, for a GrRenderTarget surface.
SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call
surface->getCanvas() to use that canvas. The caller should not delete the returned canvas;
it is owned by surface.
SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
of the requested dimensions are zero, then nullptr will be returned.
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels,
size_t rowBytes,
const SkSurfaceProps* surfaceProps = nullptr)
#In Constructors
#Line # creates Surface from SkImageInfo and Pixel_Storage ##
#Populate
#Example
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");
}
}
#StdOut
---
-x-
---
##
##
#SeeAlso MakeRasterDirectReleaseProc MakeRaster MakeRasterN32Premul SkCanvas::MakeRasterDirect
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels,
size_t rowBytes,
void (*releaseProc)(void* pixels, void* context),
void* context, const SkSurfaceProps* surfaceProps = nullptr)
#In Constructors
#Line # creates Surface from SkImageInfo and Pixel_Storage ##
#Populate
#Example
#Function
static void release_direct_surface_storage(void* pixels, void* context) {
if (pixels == context) {
SkDebugf("expected release context\n");
}
sk_free(pixels);
}
##
void draw(SkCanvas* ) {
SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
const size_t rowBytes = info.minRowBytes();
void* pixels = sk_malloc_throw(info.computeByteSize(rowBytes));
sk_sp<SkSurface> surface(SkSurface::MakeRasterDirectReleaseProc(info, pixels, rowBytes,
release_direct_surface_storage, pixels));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorWHITE);
SkPMColor* colorPtr = (SkPMColor*) pixels;
SkPMColor pmWhite = colorPtr[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", *colorPtr++ == pmWhite ? '-' : 'x');
}
SkDebugf("\n");
}
}
#StdOut
---
-x-
---
expected release context
##
##
#SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRaster
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes,
const SkSurfaceProps* surfaceProps)
#In Constructors
#Line # creates Surface from SkImageInfo ##
#Populate
#Example
void draw(SkCanvas* ) {
SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
const size_t rowBytes = 64;
sk_sp<SkSurface> surface(SkSurface::MakeRaster(info, rowBytes, nullptr));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorWHITE);
SkPixmap pixmap;
if (surface->peekPixels(&pixmap)) {
const uint32_t* colorPtr = pixmap.addr32();
SkPMColor pmWhite = colorPtr[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", colorPtr[x] == pmWhite ? '-' : 'x');
}
colorPtr += rowBytes / sizeof(colorPtr[0]);
SkDebugf("\n");
}
}
}
#StdOut
---
-x-
---
##
##
#SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo,
const SkSurfaceProps* props = nullptr)
#Populate
#Example
void draw(SkCanvas* ) {
SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
sk_sp<SkSurface> surface(SkSurface::MakeRaster(info));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorWHITE);
SkPixmap pixmap;
if (surface->peekPixels(&pixmap)) {
const uint32_t* colorPtr = pixmap.addr32();
SkPMColor pmWhite = colorPtr[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", colorPtr[x] == pmWhite ? '-' : 'x');
}
colorPtr += info.width();
SkDebugf("\n");
}
}
}
##
#SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height,
const SkSurfaceProps* surfaceProps = nullptr)
#In Constructors
#Line # creates Surface from width, height matching output ##
#Populate
#Example
void draw(SkCanvas* ) {
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(3, 3));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorWHITE);
SkPixmap pixmap;
if (surface->peekPixels(&pixmap)) {
const uint32_t* colorPtr = pixmap.addr32();
SkPMColor pmWhite = colorPtr[0];
SkPaint paint;
canvas->drawPoint(1, 1, paint);
canvas->flush(); // ensure that point was drawn
for (int y = 0; y < surface->height(); ++y) {
for (int x = 0; x < surface->width(); ++x) {
SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x');
}
colorPtr += surface->width();
SkDebugf("\n");
}
}
}
#StdOut
---
-x-
---
##
##
#SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context,
const GrBackendTexture& backendTexture,
GrSurfaceOrigin origin, int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps)
#In Constructors
#Line # creates Surface from GPU texture ##
#Populate
#Example
#Platform gpu cpu
#Image 3
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendTexture(context,
backEndTexture, kTopLeft_GrSurfaceOrigin, 0,
kRGBA_8888_SkColorType, nullptr, nullptr);
auto surfaceCanvas = gpuSurface->getCanvas();
surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
##
#SeeAlso GrBackendTexture MakeFromBackendRenderTarget MakeRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context,
const GrBackendRenderTarget& backendRenderTarget,
GrSurfaceOrigin origin,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps)
#In Constructors
#Line # creates Surface from GPU render target ##
#Populate
#Example
#ToDo remove !fiddle below once backEndTextureRenderTarget is available ##
#Platform !fiddle gpu
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendRenderTarget(context,
backEndRenderTarget, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
nullptr, nullptr);
auto surfaceCanvas = gpuSurface->getCanvas();
surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
##
#SeeAlso MakeFromBackendTexture MakeRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context,
const GrBackendTexture& backendTexture,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps)
#In Constructors
#Line # creates Surface from GPU back-end render target ##
#Populate
#Example
#ToDo example is bogus; gpuSurface should not make image ##
#Platform gpu
#Image 3
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendTextureAsRenderTarget(
context, backEndTexture, kTopLeft_GrSurfaceOrigin, 0,
kRGBA_8888_SkColorType, nullptr, nullptr);
auto surfaceCanvas = gpuSurface->getCanvas();
surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
##
#SeeAlso MakeFromBackendRenderTarget MakeRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
const SkImageInfo& imageInfo,
int sampleCount, GrSurfaceOrigin surfaceOrigin,
const SkSurfaceProps* surfaceProps,
bool shouldCreateWithMips = false)
#In Constructors
#Line # creates Surface pointing to new GPU memory buffer ##
#Populate
#Example
#Platform gpu
#Height 64
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType);
for (auto surfaceOrigin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) {
auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0,
surfaceOrigin, nullptr));
auto surfaceCanvas = gpuSurface->getCanvas();
surfaceCanvas->clear(SK_ColorWHITE);
surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
canvas->translate(0, 128);
}
##
#SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
const SkImageInfo& imageInfo, int sampleCount,
const SkSurfaceProps* props)
#Populate
#Example
#Platform cpu gpu
#Description
LCD text takes advantage of raster striping to improve resolution. Only one of
the four combinations is correct, depending on whether monitor LCD striping is
horizontal or vertical, and whether the order of the stripes is red blue green
or red green blue.
##
void draw(SkCanvas* canvas) {
auto test_draw = [](SkCanvas* surfaceCanvas) -> void {
SkPaint paint;
paint.setAntiAlias(true);
paint.setLCDRenderText(true);
paint.setColor(0xFFBBBBBB);
surfaceCanvas->drawRect(SkRect::MakeWH(128, 64), paint);
paint.setColor(SK_ColorWHITE);
paint.setTextSize(32);
surfaceCanvas->drawString("Pest", 0, 25, paint);
};
GrContext* context = canvas->getGrContext();
SkImageInfo info = SkImageInfo::MakeN32(128, 64, kOpaque_SkAlphaType);
int y = 0;
for (auto geometry : { kRGB_H_SkPixelGeometry, kBGR_H_SkPixelGeometry,
kRGB_V_SkPixelGeometry, kBGR_V_SkPixelGeometry } ) {
SkSurfaceProps props(0, geometry);
sk_sp<SkSurface> surface = context ? SkSurface::MakeRenderTarget(
context, SkBudgeted::kNo, info, 0, &props) : SkSurface::MakeRaster(info, &props);
test_draw(surface->getCanvas());
surface->draw(canvas, 0, y, nullptr);
sk_sp<SkImage> image(surface->makeImageSnapshot());
SkAutoCanvasRestore acr(canvas, true);
canvas->scale(8, 8);
canvas->drawImage(image, 12, y / 8);
y += 64;
}
}
##
#SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
const SkImageInfo& imageInfo)
#Populate
#Example
#Platform gpu
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType);
auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
auto surfaceCanvas = gpuSurface->getCanvas();
surfaceCanvas->clear(SK_ColorWHITE);
surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
##
#SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context,
const SkSurfaceCharacterization& characterization,
SkBudgeted budgeted)
#Populate
#NoExample
##
#SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method static sk_sp<SkSurface> MakeNull(int width, int height)
#In Constructors
#Line # creates Surface without backing pixels ##
#Populate
#Example
SkDebugf("SkSurface::MakeNull(0, 0) %c= nullptr\n", SkSurface::MakeNull(0, 0) == nullptr ?
'=' : '!');
const int w = 37;
const int h = 1000;
auto surf = SkSurface::MakeNull(w, h);
auto nullCanvas = surf->getCanvas();
nullCanvas->drawPaint(SkPaint()); // does not crash, nothing draws
SkDebugf("surf->makeImageSnapshot() %c= nullptr\n", surf->makeImageSnapshot() == nullptr ?
'=' : '!');
#StdOut
SkSurface::MakeNull(0, 0) == nullptr
surf->makeImageSnapshot() == nullptr
##
##
#SeeAlso MakeRaster MakeRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Subtopic Property
#Line # member values ##
##
#Method int width() const
#In Property
#Line # returns pixel column count ##
#Populate
#Example
const int width = 37;
const int height = 1000;
auto surf = SkSurface::MakeNull(width, height);
auto nullCanvas = surf->getCanvas();
SkDebugf("surface width=%d canvas width=%d\n", surf->width(),
nullCanvas->getBaseLayerSize().fWidth);
#StdOut
surface width=37 canvas width=37
##
##
#SeeAlso height()
#Method ##
# ------------------------------------------------------------------------------
#Method int height() const
#In Property
#Line # returns pixel row count ##
#Populate
#Example
const int width = 37;
const int height = 1000;
auto surf = SkSurface::MakeNull(width, height);
auto nullCanvas = surf->getCanvas();
SkDebugf("surface height=%d canvas height=%d\n", surf->height(),
nullCanvas->getBaseLayerSize().fHeight);
#StdOut
surface height=1000 canvas height=1000
##
##
#SeeAlso width()
#Method ##
# ------------------------------------------------------------------------------
#Method uint32_t generationID()
#In Property
#Line # returns unique ID ##
#Populate
#Example
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
for (int i = 0; i < 3; ++i) {
SkDebugf("surface generationID: %d\n", surface->generationID());
if (0 == i) {
surface->getCanvas()->drawColor(SK_ColorBLACK);
} else {
surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
}
}
#StdOut
surface generationID: 1
surface generationID: 2
surface generationID: 3
##
##
#SeeAlso notifyContentWillChange ContentChangeMode getCanvas
#Method ##
# ------------------------------------------------------------------------------
#Enum ContentChangeMode
#Line # parameter options for notifyContentWillChange ##
#Code
enum ContentChangeMode {
kDiscard_ContentChangeMode,
kRetain_ContentChangeMode,
};
##
ContentChangeMode members are parameters to notifyContentWillChange.
#Const kDiscard_ContentChangeMode
#Line # discards surface on change ##
Pass to notifyContentWillChange to discard surface contents when
the surface is cleared or overwritten.
##
#Const kRetain_ContentChangeMode
#Line # preserves surface on change ##
Pass to notifyContentWillChange when to preserve surface contents.
If a snapshot has been generated, this copies the Surface contents.
##
#SeeAlso notifyContentWillChange generationID
#Enum ##
# ------------------------------------------------------------------------------
#ToDo not crazy about misc catagory -- hopefully will become clear with time
##
#Subtopic Miscellaneous
#Line # other functions ##
##
#Method void notifyContentWillChange(ContentChangeMode mode)
#In Miscellaneous
#Line # notifies that contents will be changed outside of Skia ##
#Populate
#Example
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
for (int i = 0; i < 3; ++i) {
SkDebugf("surface generationID: %d\n", surface->generationID());
if (0 == i) {
surface->getCanvas()->drawColor(SK_ColorBLACK);
} else {
surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
}
}
##
#SeeAlso ContentChangeMode generationID
#Method ##
# ------------------------------------------------------------------------------
#Enum BackendHandleAccess
#Line # options to read and write back-end object ##
#Code
enum BackendHandleAccess {
kFlushRead_BackendHandleAccess,
kFlushWrite_BackendHandleAccess,
kDiscardWrite_BackendHandleAccess,
};
static const BackendHandleAccess kFlushRead_TextureHandleAccess =
kFlushRead_BackendHandleAccess;
static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
kFlushWrite_BackendHandleAccess;
static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
kDiscardWrite_BackendHandleAccess;
##
#Const kFlushRead_BackendHandleAccess 0
#Line # back-end object is readable ##
Caller may read from the back-end object.
##
#Const kFlushWrite_BackendHandleAccess 1
#Line # back-end object is writable ##
Caller may write to the back-end object.
##
#Const kDiscardWrite_BackendHandleAccess 2
#Line # back-end object must be overwritten ##
Caller must overwrite the entire back-end object.
##
#NoExample
// todo: need to update example to use GrBackendTexture instead of GrBackendObject
#Platform gpu
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
sk_sp<SkSurface> gpuSurface = SkSurface::MakeRenderTarget(
context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(10, 10));
int y = 20;
SkString str;
paint.setTextSize(16);
for (auto access : { SkSurface::kFlushRead_BackendHandleAccess,
SkSurface::kFlushWrite_BackendHandleAccess,
SkSurface::kDiscardWrite_BackendHandleAccess } ) {
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
str.printf("uniqueID=%d", image->uniqueID());
canvas->drawString(str, 20, y += 20, paint);
GrBackendTexture backendTex = gpuSurface->getBackendTexture(access);
str.printf("backendTex is %svalid", backendTex.isValid() ? '' : 'not ');
canvas->drawString(str, 20, y += 20, paint);
}
sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
str.printf("final image uniqueID=%d", image->uniqueID());
canvas->drawString(str, 20, y += 20, paint);
##
#SeeAlso getBackendTexture getBackendRenderTarget
#Enum ##
# ------------------------------------------------------------------------------
#Method GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess)
#In Property
#Line # returns the GPU reference to texture ##
#Populate
#NoExample
##
#SeeAlso GrBackendTexture BackendHandleAccess getBackendRenderTarget
#Method ##
# ------------------------------------------------------------------------------
#Method GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess)
#In Property
#Line # returns the GPU reference to render target ##
#Populate
#NoExample
##
#SeeAlso GrBackendRenderTarget BackendHandleAccess getBackendTexture
#Method ##
# ------------------------------------------------------------------------------
#Method SkCanvas* getCanvas()
#In Property
#Line # returns Canvas that draws into Surface ##
#Populate
#Example
#Height 64
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(64, 64));
SkCanvas* surfaceCanvas = surface->getCanvas();
surfaceCanvas->clear(SK_ColorBLUE);
SkPaint paint;
paint.setTextSize(40);
surfaceCanvas->drawString("\xF0\x9F\x98\x81", 12, 45, paint);
surface->draw(canvas, 0, 0, nullptr);
##
#SeeAlso makeSurface makeImageSnapshot draw
#Method ##
# ------------------------------------------------------------------------------
#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo)
#In Constructors
#Line # creates a compatible Surface ##
#Populate
#Example
#Height 96
sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
big->getCanvas()->clear(SK_ColorRED);
lil->getCanvas()->clear(SK_ColorBLACK);
SkPixmap pixmap;
if (big->peekPixels(&pixmap)) {
SkBitmap bigBits;
bigBits.installPixels(pixmap);
canvas->drawBitmap(bigBits, 0, 0);
}
if (lil->peekPixels(&pixmap)) {
SkBitmap lilBits;
lilBits.installPixels(pixmap);
canvas->drawBitmap(lilBits, 64, 64);
}
##
#SeeAlso makeImageSnapshot getCanvas draw
#Method ##
# ------------------------------------------------------------------------------
#Method sk_sp<SkImage> makeImageSnapshot()
#In Constructors
#Line # creates Image capturing Surface contents ##
#Populate
#Example
#Height 64
sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
big->getCanvas()->clear(SK_ColorRED);
lil->getCanvas()->clear(SK_ColorBLACK);
sk_sp<SkImage> early(big->makeImageSnapshot());
lil->draw(big->getCanvas(), 16, 16, nullptr);
sk_sp<SkImage> later(big->makeImageSnapshot());
canvas->drawImage(early, 0, 0);
canvas->drawImage(later, 128, 0);
##
#SeeAlso draw getCanvas
#Method ##
# ------------------------------------------------------------------------------
#Method sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds)
#In Constructors
#Line # creates Image capturing subset of Surface contents ##
#Populate
#Example
#Height 64
sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
big->getCanvas()->clear(SK_ColorRED);
lil->getCanvas()->clear(SK_ColorBLACK);
sk_sp<SkImage> early(big->makeImageSnapshot());
lil->draw(big->getCanvas(), 16, 16, nullptr);
sk_sp<SkImage> later(big->makeImageSnapshot({0, 0, 16, 16}));
canvas->drawImage(early, 0, 0);
canvas->drawImage(later, 0, 0);
##
#SeeAlso draw getCanvas
#Method ##
# ------------------------------------------------------------------------------
#Subtopic Pixels
#Line # functions with pixel access ##
##
#Method void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint)
#In Pixels
#Line # draws Surface contents to canvas ##
#Populate
#Example
#Height 64
sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
big->getCanvas()->clear(SK_ColorRED);
lil->getCanvas()->clear(SK_ColorBLACK);
lil->draw(big->getCanvas(), 16, 16, nullptr);
SkPixmap pixmap;
if (big->peekPixels(&pixmap)) {
SkBitmap bigBits;
bigBits.installPixels(pixmap);
canvas->drawBitmap(bigBits, 0, 0);
}
##
#SeeAlso makeImageSnapshot getCanvas
#Method ##
# ------------------------------------------------------------------------------
#Method bool peekPixels(SkPixmap* pixmap)
#In Pixels
#Line # copies Surface parameters to Pixmap ##
#Populate
#Example
#Height 64
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorRED);
SkPaint paint;
paint.setTextSize(40);
surfCanvas->drawString("&", 16, 48, paint);
SkPixmap pixmap;
if (surf->peekPixels(&pixmap)) {
SkBitmap surfBits;
surfBits.installPixels(pixmap);
canvas->drawBitmap(surfBits, 0, 0);
}
##
#SeeAlso readPixels writePixels
#Method ##
# ------------------------------------------------------------------------------
#Method bool readPixels(const SkPixmap& dst, int srcX, int srcY)
#In Pixels
#Line # copies Rect of pixels ##
Copies Rect of pixels to dst.
Source Rect corners are (srcX, srcY) and Surface (width(), height()).
Destination Rect corners are (0, 0) and (dst.width(), dst.height()).
Copies each readable pixel intersecting both rectangles, without scaling,
converting to dst.colorType() and dst.alphaType() if required.
Pixels are readable when Surface is raster, or backed by a GPU.
The destination pixel storage must be allocated by the caller.
Pixel values are converted only if Color_Type and Alpha_Type
do not match. Only pixels within both source and destination rectangles
are copied. dst contents outside Rect intersection are unchanged.
Pass negative values for srcX or srcY to offset pixels across or down destination.
Does not copy, and returns false if:
#List
# Source and destination rectangles do not intersect. ##
# Pixmap pixels could not be allocated. ##
# dst.rowBytes() is too small to contain one row of pixels. ##
##
#Param dst storage for pixels copied from Surface ##
#Param srcX offset into readable pixels on x-axis; may be negative ##
#Param srcY offset into readable pixels on y-axis; may be negative ##
#Return true if pixels were copied ##
#Example
#Height 32
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorRED);
SkPaint paint;
paint.setTextSize(40);
surfCanvas->drawString("&", 0, 32, paint);
std::vector<SkPMColor> storage;
storage.resize(surf->width() * surf->height());
SkPixmap pixmap(SkImageInfo::MakeN32Premul(32, 32), &storage.front(),
surf->width() * sizeof(storage[0]));
if (surf->readPixels(pixmap, 0, 0)) {
SkBitmap surfBits;
surfBits.installPixels(pixmap);
canvas->drawBitmap(surfBits, 0, 0);
}
##
#SeeAlso peekPixels writePixels
#Method ##
# ------------------------------------------------------------------------------
#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
int srcX, int srcY)
Copies Rect of pixels from Canvas into dstPixels.
Source Rect corners are (srcX, srcY) and Surface (width(), height()).
Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
Copies each readable pixel intersecting both rectangles, without scaling,
converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Pixels are readable when Surface is raster, or backed by a GPU.
The destination pixel storage must be allocated by the caller.
Pixel values are converted only if Color_Type and Alpha_Type
do not match. Only pixels within both source and destination rectangles
are copied. dstPixels contents outside Rect intersection are unchanged.
Pass negative values for srcX or srcY to offset pixels across or down destination.
Does not copy, and returns false if:
#List
# Source and destination rectangles do not intersect. ##
# Surface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
# dstRowBytes is too small to contain one row of pixels. ##
##
#Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ##
#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
#Param srcX offset into readable pixels on x-axis; may be negative ##
#Param srcY offset into readable pixels on y-axis; may be negative ##
#Return true if pixels were copied ##
#Example
#Height 64
#Description
A black oval drawn on a red background provides an image to copy.
readPixels copies one quarter of the Surface into each of the four corners.
The copied quarter ovals overdraw the original oval.
##
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorRED);
SkPaint paint;
surfCanvas->drawOval({4, 8, 58, 54}, paint);
SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
for (int x : { 32, -32 } ) {
for (int y : { 32, -32 } ) {
surf->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
}
}
sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
canvas->drawImage(image, 0, 0);
##
#SeeAlso peekPixels writePixels
#Method ##
# ------------------------------------------------------------------------------
#Method bool readPixels(const SkBitmap& dst, int srcX, int srcY)
Copies Rect of pixels from Surface into bitmap.
Source Rect corners are (srcX, srcY) and Surface (width(), height()).
Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Copies each readable pixel intersecting both rectangles, without scaling,
converting to dst.colorType() and dst.alphaType() if required.
Pixels are readable when Surface is raster, or backed by a GPU.
The destination pixel storage must be allocated by the caller.
Pixel values are converted only if Color_Type and Alpha_Type
do not match. Only pixels within both source and destination rectangles
are copied. dst contents outside Rect intersection are unchanged.
Pass negative values for srcX or srcY to offset pixels across or down destination.
Does not copy, and returns false if:
#List
# Source and destination rectangles do not intersect. ##
# Surface pixels could not be converted to dst.colorType() or dst.alphaType(). ##
# dst pixels could not be allocated. ##
# dst.rowBytes() is too small to contain one row of pixels. ##
##
#Param dst storage for pixels copied from Surface ##
#Param srcX offset into readable pixels on x-axis; may be negative ##
#Param srcY offset into readable pixels on y-axis; may be negative ##
#Return true if pixels were copied ##
#Example
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorGREEN);
SkPaint paint;
surfCanvas->drawOval({2, 10, 58, 54}, paint);
SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
SkBitmap bitmap;
bitmap.setInfo(info);
bitmap.allocPixels();
for (int x : { 32, -32 } ) {
for (int y : { 32, -32 } ) {
surf->readPixels(bitmap, x, y);
}
}
canvas->drawBitmap(bitmap, 0, 0);
##
#SeeAlso peekPixels writePixels
#Method ##
# ------------------------------------------------------------------------------
#Method void writePixels(const SkPixmap& src, int dstX, int dstY)
#In Pixels
#Line # copies Rect of pixels ##
Copies Rect of pixels from the src Pixmap to the Surface.
Source Rect corners are (0, 0) and (src.width(), src.height()).
Destination Rect corners are (dstX, dstY) and
#Formula # (dstX + Surface width(), dstY + Surface height()) ##.
Copies each readable pixel intersecting both rectangles, without scaling,
converting to Surface SkColorType and SkAlphaType if required.
#Param src storage for pixels to copy to Surface ##
#Param dstX x-axis position relative to Surface to begin copy; may be negative ##
#Param dstY y-axis position relative to Surface to begin copy; may be negative ##
#Example
#Image 4
#Height 96
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorRED);
SkPaint paint;
paint.setTextSize(40);
surfCanvas->drawString("&", 16, 40, paint);
SkPixmap pixmap;
if (surf->peekPixels(&pixmap)) {
surf->writePixels(pixmap, 25, 25);
sk_sp<SkImage> image(surf->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
}
##
#SeeAlso readPixels peekPixels
#Method ##
# ------------------------------------------------------------------------------
#Method void writePixels(const SkBitmap& src, int dstX, int dstY)
Copies Rect of pixels from the src Bitmap to the Surface.
Source Rect corners are (0, 0) and (src.width(), src.height()).
Destination Rect corners are (dstX, dstY) and
#Formula # (dstX + Surface width(), dstY + Surface height()) ##.
Copies each readable pixel intersecting both rectangles, without scaling,
converting to Surface SkColorType and SkAlphaType if required.
#Param src storage for pixels to copy to Surface ##
#Param dstX x-axis position relative to Surface to begin copy; may be negative ##
#Param dstY y-axis position relative to Surface to begin copy; may be negative ##
#Example
#Image 4
#Height 96
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
auto surfCanvas = surf->getCanvas();
surfCanvas->clear(SK_ColorGREEN);
surf->writePixels(source, 25, 25);
sk_sp<SkImage> image(surf->makeImageSnapshot());
canvas->drawImage(image, 0, 0);
##
#SeeAlso readPixels peekPixels
#Method ##
# ------------------------------------------------------------------------------
#Method const SkSurfaceProps& props() const
#In Property
#Line # returns Surface_Properties ##
#Populate
#Example
const char* names[] = { "Unknown", "RGB_H", "BGR_H", "RGB_V", "BGR_V" };
sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
SkDebugf("surf.props(): k%s_SkPixelGeometry\n", names[surf->props().pixelGeometry()]);
#StdOut
surf.props(): kRGB_H_SkPixelGeometry
##
##
#SeeAlso SkSurfaceProps
#Method ##
# ------------------------------------------------------------------------------
#Subtopic Utility
#Line # rarely called management functions ##
##
#Method void flush()
#In Utility
#Line # resolves pending I/O ##
#Populate
#NoExample
##
#SeeAlso GrBackendSemaphore
#Method ##
# ------------------------------------------------------------------------------
#Method GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,
GrBackendSemaphore signalSemaphores[])
#In Utility
#Line # resolves pending I/O, and signal ##
#Populate
#NoExample
##
#SeeAlso wait GrBackendSemaphore
#Method ##
# ------------------------------------------------------------------------------
#Method bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores)
#In Utility
#Line # pauses commands until signaled ##
#Populate
#NoExample
#ToDo this is copy and paste silliness masquerading as an example. Probably need gpu
globals and definitely need gpu expertise to make a real example out of this
also, note need to replace GrBackendObject with GrBackendTexture
##
#Platform gpu
#Height 64
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
GrBackendSemaphore semaphore;
sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64));
surface->flushAndSignalSemaphores(1, &semaphore);
sk_sp<SkImage> image = surface->makeImageSnapshot();
GrBackendTexture backendTex = image->getBackendTexture(false); // unused
SkASSERT(backendTex.isValid());
const SkImageInfo childImageInfo = SkImageInfo::Make(64, 64,
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
childImageInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr));
GrBackendTexture backendTexture;
sk_sp<SkImage> childImage = SkImage::MakeFromTexture(context,
backendTexture, // undefined
kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr);
SkCanvas* childCanvas = childSurface->getCanvas();
childCanvas->clear(SK_ColorRED);
childSurface->wait(1, &semaphore);
childCanvas->drawImage(childImage, 32, 0);
childSurface->draw(canvas, 0, 0, nullptr);
##
#SeeAlso flushAndSignalSemaphores GrBackendSemaphore
#Method ##
# ------------------------------------------------------------------------------
#Method bool characterize(SkSurfaceCharacterization* characterization) const
#In Utility
#Line # sets Surface_Characterization for threaded GPU processing ##
#Populate
#Example
#Platform gpu
#Height 64
SkPaint paint;
paint.setTextSize(32);
GrContext* context = canvas->getGrContext();
if (!context) {
canvas->drawString("GPU only!", 20, 40, paint);
return;
}
sk_sp<SkSurface> gpuSurface = SkSurface::MakeRenderTarget(
context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64));
SkSurfaceCharacterization characterization;
if (!gpuSurface->characterize(&characterization)) {
canvas->drawString("characterization unsupported", 20, 40, paint);
return;
}
// start of threadable work
SkDeferredDisplayListRecorder recorder(characterization);
SkCanvas* subCanvas = recorder.getCanvas();
subCanvas->clear(SK_ColorGREEN);
std::unique_ptr<SkDeferredDisplayList> displayList = recorder.detach();
// end of threadable work
gpuSurface->draw(displayList.get());
sk_sp<SkImage> img = gpuSurface->makeImageSnapshot();
canvas->drawImage(std::move(img), 0, 0);
##
#SeeAlso draw() SkSurfaceCharacterization SkDeferredDisplayList
#Method ##
# ------------------------------------------------------------------------------
#Method bool draw(SkDeferredDisplayList* deferredDisplayList)
#Populate
#Example
#Height 64
#Platform gpu cpu
SkPaint paint;
paint.setTextSize(16);
sk_sp<SkSurface> gpuSurface = SkSurface::MakeRasterN32Premul(64, 64);
SkSurfaceCharacterization characterization;
if (!gpuSurface->characterize(&characterization)) {
canvas->drawString("characterization unsupported", 20, 40, paint);
return;
}
// start of threadable work
SkDeferredDisplayListRecorder recorder(characterization);
SkCanvas* subCanvas = recorder.getCanvas();
subCanvas->clear(SK_ColorGREEN);
std::unique_ptr<SkDeferredDisplayList> displayList = recorder.detach();
// end of threadable work
gpuSurface->draw(displayList.get());
sk_sp<SkImage> img = gpuSurface->makeImageSnapshot();
canvas->drawImage(std::move(img), 0, 0);
##
#SeeAlso characterize() SkSurfaceCharacterization SkDeferredDisplayList
#Method ##
#Class SkSurface ##
#Topic Surface ##