Options
These globals are now defined:
double duration; // The requested duration of the animation. double frame; // A value in [0, 1] of where we are in the animation.
This global is now defined:
GrBackendRenderTarget backEndRenderTarget;
GrBackendTexture backEndTextureRenderTarget;
Optional source image
These globals are now defined:
SkBitmap source; sk_sp<SkImage> image; GrBackendTexture backEndTexture; // GPU Only.
Note:
Adding comments with SK_FOLD_START and SK_FOLD_END creates foldable code
blocks.
These blocks will be folded by default and are useful for highlighting specific lines of code.
You can also use the keyboard shortcuts Ctrl+S and Ctrl+E in the code editor to set them.
These blocks will be folded by default and are useful for highlighting specific lines of code.
You can also use the keyboard shortcuts Ctrl+S and Ctrl+E in the code editor to set them.
xxxxxxxxxx
163
bool GPU = false;
void drawText(SkCanvas * canvas, int n, int x, int y)
{
auto paint = SkPaint();
paint.setColor(SK_ColorWHITE);
for (int i = 0; i < n; i++)
{
std::string text = "drawn ";
text += std::to_string(n);
text += " time";
if (i != 0) text += "s";
if (!GPU)
{
canvas->drawString(text.c_str(), x, y, SkFont(nullptr, 12), paint);
}
else
{
canvas->save();
canvas->translate(x, y);
canvas->drawString(text.c_str(), 0, 0, SkFont(nullptr, 12), paint);
canvas->restore();
}
}
}
void drawMatrix(SkCanvas * canvas, int count, int max_lines, int spacing)
{
max_lines++;
int n = 0;
int column = 0;
int line = 1;
for (int i = 0; i < count; i++)
{
n = i + 1;
if (line == max_lines)
{
line = 1;
column += spacing;
}
drawText(canvas, n, column, 20 * line);
line++;
}
}
void draw(SkCanvas* canvas) {
auto txtpaint = SkPaint();
txtpaint.setColor(SK_ColorWHITE);
canvas->drawColor(SK_ColorBLACK);
auto sksl = SkRuntimeEffect::MakeForShader(
SkString(
"uniform shader input_;\n"
"uniform shader inputAlpha;\n"
"\n"
"half4 main(float2 cord) {\n"
" half4 color = input_.eval(cord);\n"
// return zero if alpha is zero
" if (color.a == 0) return vec4(0,0,0,1);\n"
" int alpha = (int)(255.0 * inputAlpha.eval(cord).a);\n"
// return color if input alpha is 0, this means we only drawn this pixel once
// Skia's overdraw canvas increases the alpha of a pixel each time it drawn touched
// R G B A
" if (alpha == 0) {\n"
// apply greyscale to the overdraw canvas in order to isolate the overdraw colors
" return half4(vec3((color.r + color.g + color.b) / 3), 1);\n"
" }\n"
" return half4(1,0,0,1);\n"
"}\n")
);
if (sksl.effect == nullptr) {
auto text = sksl.errorText;
auto text_c = text.c_str();
SkDebugf("SHADER ERROR!\n");
SkDebugf("%s\n", text_c);
canvas->drawString("SHADER ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
canvas->drawString(text_c, 0, 52, SkFont(nullptr, 12), txtpaint);
return;
}
auto surface = canvas->getSurface();
GrRecordingContext * context = surface ? surface->recordingContext() : nullptr;
GPU = surface && context;
int w = canvas->imageInfo().width();
int h = canvas->imageInfo().height();
auto offscreenInfo = canvas->imageInfo().makeWH(w, h);
auto offscreenAlphaInfo = SkImageInfo::MakeA8(w, h);
auto offscreenSurface =
GPU ? SkSurface::MakeRenderTarget(canvas->getSurface()->recordingContext(), SkBudgeted::kNo, offscreenInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr)
: SkSurface::MakeRaster(offscreenInfo, kTopLeft_GrSurfaceOrigin, nullptr);
auto offscreenAlphaSurface =
GPU ? SkSurface::MakeRenderTarget(canvas->getSurface()->recordingContext(), SkBudgeted::kNo, offscreenAlphaInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr)
: SkSurface::MakeRaster(offscreenAlphaInfo, kTopLeft_GrSurfaceOrigin, nullptr);
if (!offscreenSurface || !offscreenAlphaSurface) {
SkDebugf("SURFACE ERROR!\n");
canvas->drawString("SURFACE ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
return;
}
auto imageCanvas = offscreenSurface->getCanvas();
auto alphaCnvas = offscreenAlphaSurface->getCanvas();
if (!imageCanvas || !alphaCnvas) {
SkDebugf("CANVAS ERROR!\n");
canvas->drawString("CANVAS ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
return;
}
auto overdrawCanvas = SkOverdrawCanvas(alphaCnvas);
auto nWayCanvas = SkNWayCanvas(w, h);
nWayCanvas.addCanvas(&overdrawCanvas);
nWayCanvas.addCanvas(imageCanvas);
drawMatrix(&nWayCanvas, 20, 20, 50);
nWayCanvas.flush();
auto imageAlpha = offscreenAlphaSurface->makeImageSnapshot();
auto image_ = offscreenSurface->makeImageSnapshot();
if (!image_ || !imageAlpha) {
SkDebugf("SNAPSHOT ERROR!\n");
canvas->drawString("SNAPSHOT ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
return;
}
auto imageAlphaShader = imageAlpha->makeShader(SkSamplingOptions());
auto imageShader = image_->makeShader(SkSamplingOptions());
if (!imageAlphaShader || !imageShader) {
SkDebugf("MAKE SHADER ERROR!\n");
canvas->drawString("MAKE SHADER ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
return;
}
SkRuntimeShaderBuilder builder(sksl.effect);
builder.child("input_") = imageShader;
builder.child("inputAlpha") = imageAlphaShader;
auto ourShader = builder.makeShader();
if (!ourShader) {
SkDebugf("COMBINE SHADER ERROR!\n");
canvas->drawString("COMBINE SHADER ERROR!", 20, 40, SkFont(nullptr, 12), txtpaint);
return;
}
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
paint.setShader(ourShader);
canvas->drawPaint(paint);
SkDebugf("DRAWN!\n");
}