40#define STROKE_WIDTH SkIntToScalar(10)
94 scale.setScale(0.5f, 0.5f);
95 scale.postTranslate(25.f, 25.f);
102 center0, (pts[1].fX - pts[0].fX) / 2,
118 void onOnceBeforeDraw()
override {
127 SkISize getISize()
override {
return {860, 820}; }
129 void onDraw(
SkCanvas* canvas)
override {
132 SkRect r = { 0, 0, 100, 50 };
139 paint.setMaskFilter(fMaskFilters[
f]);
140 paint.setAlpha(fAlpha);
145 constexpr Proc procs[] = {
150 canvas->
scale(scales[
s], scales[
s]);
151 this->drawProcs(canvas, r,
paint,
false, procs,
std::size(procs));
153 this->drawProcs(canvas, r, paintWithRadial,
false, procs,
std::size(procs));
157 this->drawProcs(canvas, r, paintWithRadial,
true, procs,
std::size(procs));
168 bool doClip,
const Proc procs[],
size_t procsCount) {
170 for (
size_t i = 0;
i < procsCount; ++
i) {
177 procs[
i](canvas, r,
paint);
181 canvas->translate(0, r.height() * 4/3);
187 const int fGMWidth = 1200;
188 const int fPadding = 10;
189 const int fMargin = 100;
191 const int widths[] = {25, 5, 5, 100, 150, 25};
192 const int heights[] = {100, 100, 5, 25, 150, 25};
194 const float radii[] = {20, 5, 10};
196 canvas->translate(50,20);
210 for (
size_t j = 0 ; j <
std::size(radii) ; j++) {
211 float radius = radii[j];
212 for (
size_t k = 0 ; k <
std::size(styles) ; k++) {
226 if (cur_x + bm.
width() >= fGMWidth - fMargin) {
228 cur_y += max_height + fPadding;
235 canvas->drawImage(bm.
asImage(), 0.f, 0.f);
238 cur_x += bm.
width() + fPadding;
239 if (bm.
height() > max_height)
260 *errorMsg =
"Not supported when recording, relies on canvas->makeSurface()";
265 if (fRecalcMasksForAnimation || !fActualMasks[0][0][0] || ctxID != fLastContextUniqueID) {
266 if (fRecalcMasksForAnimation) {
268 this->prepareReferenceMasks();
270 this->prepareActualMasks(canvas);
271 this->prepareMaskDifferences(canvas);
272 fLastContextUniqueID = ctxID;
273 fRecalcMasksForAnimation =
false;
276 static constexpr float kMargin = 30;
278 for (
auto w : kSizes) {
284 for (
size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
285 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
286 for (
size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
287 auto h = kSizes[heightIdx];
289 for (
size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
290 auto w = kSizes[widthIdx];
296 img = fReferenceMasks[sigmaIdx][heightIdx][widthIdx].
get();
299 img = fActualMasks[sigmaIdx][heightIdx][widthIdx].
get();
302 img = fMaskDifferences[sigmaIdx][heightIdx][widthIdx].
get();
308 auto pad = PadForSigma(sigma);
315 stroke.setStrokeWidth(0.f);
332 fRecalcMasksForAnimation =
true;
337 void prepareReferenceMasks() {
338 auto create_reference_mask = [](
int w,
int h,
float sigma,
int numSubpixels) {
339 int pad = PadForSigma(sigma);
340 int maskW =
w + 2 * pad;
341 int maskH =
h + 2 * pad;
345 sigma *= numSubpixels;
347 auto def_integral_approx = [
scale](
float a,
float b) {
348 return 0.5f * (std::erf(
b *
scale) - std::erf(
a *
scale));
353 std::unique_ptr<float[]> row(
new float[maskW * numSubpixels]);
354 for (
int col = 0; col < maskW * numSubpixels; ++col) {
356 float ldiff = numSubpixels * pad - (col + 0.5f);
357 float rdiff = ldiff +
w;
358 row[col] = def_integral_approx(ldiff, rdiff);
363 std::unique_ptr<float[]> accums(
new float[maskW]);
364 const float accumScale = 1.f / (numSubpixels * numSubpixels);
365 for (
int y = 0;
y < maskH; ++
y) {
367 std::fill_n(accums.get(), maskW, 0);
368 for (
int ys = 0; ys < numSubpixels; ++ys) {
374 float tdiff = numSubpixels * pad - (
y * numSubpixels + ys + 0.5f);
375 float bdiff = tdiff +
h;
376 auto integral = def_integral_approx(tdiff, bdiff);
377 for (
int x = 0;
x < maskW; ++
x) {
378 for (
int xs = 0; xs < numSubpixels; ++xs) {
379 int rowIdx =
x * numSubpixels + xs;
380 accums[
x] += integral * row[rowIdx];
384 for (
int x = 0;
x < maskW; ++
x) {
385 auto result = accums[
x] * accumScale;
394 const int numSubpixels = fRecalcMasksForAnimation ? 2 : 8;
396 for (
size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
397 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
398 for (
size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
399 auto h = kSizes[heightIdx];
400 for (
size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
401 auto w = kSizes[widthIdx];
402 fReferenceMasks[sigmaIdx][heightIdx][widthIdx] =
403 create_reference_mask(
w,
h, sigma, numSubpixels);
409 void prepareActualMasks(
SkCanvas* canvas) {
410 for (
size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
411 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
412 for (
size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
413 auto h = kSizes[heightIdx];
414 for (
size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
415 auto w = kSizes[widthIdx];
416 auto pad = PadForSigma(sigma);
432 surf->getCanvas()->drawRect(
rect,
paint);
433 fActualMasks[sigmaIdx][heightIdx][widthIdx] = surf->makeImageSnapshot();
439 void prepareMaskDifferences(
SkCanvas* canvas) {
440 for (
size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
441 for (
size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
442 for (
size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
443 const auto& r = fReferenceMasks[sigmaIdx][heightIdx][widthIdx];
444 const auto&
a = fActualMasks[sigmaIdx][heightIdx][widthIdx];
445 auto&
d = fMaskDifferences[sigmaIdx][heightIdx][widthIdx];
465 static constexpr float kGreenifyM[] = {0, 0, 0, 0, 0,
472 paint.setColorFilter(std::move(greenifyCF));
476 d = surf->makeImageSnapshot();
486 inline static constexpr int kSizes[] = {1, 2, 4, 8, 16, 32};
487 inline static constexpr float kSigmas[] = {0.5f, 1.2f, 2.3f, 3.9f, 7.4f};
488 inline static constexpr size_t kNumSizes =
std::size(kSizes);
489 inline static constexpr size_t kNumSigmas =
std::size(kSigmas);
493 sk_sp<SkImage> fMaskDifferences[kNumSigmas][kNumSizes][kNumSizes];
494 int32_t fLastContextUniqueID;
496 float fSigmaAnimationBoost = 0;
497 bool fRecalcMasksForAnimation =
false;
511 static constexpr float kSigmas[] = {0.5f, 1.2f, 2.3f, 3.9f, 7.4f};
512 static constexpr size_t kNumSigmas =
std::size(kSigmas);
516 std::vector<SkMatrix> matrices;
523 matrices.back().preScale(1.1f, .5f);
526 matrices.back().preScale(3.f, .1f);
535 matrices.back().preSkew(.3f, -.5f);
538 for (
const auto&
m : matrices) {
540 m.mapRect(&mapped,
kRect);
543 float blurPad = 2.f*kSigmas[kNumSigmas - 1];
544 bounds.outset(blurPad, blurPad);
546 for (
auto sigma : kSigmas) {
550 for (
const auto&
m : matrices) {
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
static unsigned mirror(SkFixed fx, int max)
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
@ kNormal_SkBlurStyle
fuzzy inside and outside
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kUnknown_SkColorType
uninitialized
constexpr SkColor SK_ColorRED
constexpr SkColor SK_ColorBLACK
constexpr SkColor SK_ColorGREEN
constexpr SkColor SK_ColorWHITE
#define sk_float_ceil2int(x)
#define sk_float_round2int(x)
std::unique_ptr< uint8_t, SkFunctionObject< SkMaskBuilder::FreeImage > > SkAutoMaskFreeImage
#define SkScalarAve(a, b)
static SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t)
#define SK_ScalarRoot2Over2
constexpr uint8_t SkToU8(S x)
static void draw_donut(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
static void draw_donut_skewed(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
static void fill_rect(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024)
void(* PaintProc)(SkPaint *, SkScalar width)
static sk_sp< SkShader > make_radial()
void(* Proc)(SkCanvas *, const SkRect &, const SkPaint &)
BlurRectGM(const char name[], U8CPU alpha)
uint32_t contextID() const
virtual GrDirectContext * asDirectContext()
GrRecordingContextPriv priv()
bool installMaskPixels(SkMaskBuilder &mask)
void allocPixels(const SkImageInfo &info, size_t rowBytes)
sk_sp< SkImage > asImage() const
uint8_t * getAddr8(int x, int y) const
static bool BlurRect(SkScalar sigma, SkMaskBuilder *dst, const SkRect &src, SkBlurStyle, SkIPoint *margin=nullptr, SkMaskBuilder::CreateMode createMode=SkMaskBuilder::kComputeBoundsAndRenderImage_CreateMode)
static SkScalar SK_SPI ConvertRadiusToSigma(SkScalar radius)
void drawRect(const SkRect &rect, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void translate(SkScalar dx, SkScalar dy)
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
virtual GrRecordingContext * recordingContext() const
void clear(SkColor color)
void drawPath(const SkPath &path, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
SkImageInfo imageInfo() const
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
static SkMatrix RotateDeg(SkScalar deg)
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
void setColor(SkColor color)
@ kStroke_Style
set to stroke geometry
void setShader(sk_sp< SkShader > shader)
void onOnceBeforeDraw() override
SkISize getISize() override
SkString getName() const override
DrawResult onDraw(SkCanvas *canvas, SkString *errorMsg) override
bool onAnimate(double nanos) override
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Optional< SkRect > bounds
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
sk_sp< SkBlender > blender SkRect rect
PODArray< SkColor > colors
static float SineWave(double time, float periodInSecs, float phaseInSecs, float min, float max)
constexpr std::array< std::array< float, 2 >, 2 > kRect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static SkPath scale(const SkPath &path, SkScalar scale)
SkSamplingOptions(SkFilterMode::kLinear))
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkColorType colorType() const
static SkImageInfo MakeA8(int width, int height)
void set(float x, float y)
SkRect makeSorted() const
static constexpr SkRect MakeEmpty()
void setWH(float width, float height)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
constexpr float height() const
constexpr float width() const
static constexpr SkRect MakeWH(float w, float h)