blob: 9eb682c5c6299f4ebe567e8d6159da702fc721cc [file]
/*
* Copyright 2026 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
// Tests clipRRect cases that Graphite should handle with an analytic shader.
DEF_SIMPLE_GM(clip_rrects_analytic, canvas, 360, 325) {
const SkRect baseRect = {0, 0, 32, 32};
auto makeRRect = [&](bool tl, bool tr, bool br, bool bl) {
const float cornerRadius = 8;
const SkVector radii[4] = {
{tl ? cornerRadius : 0.f, tl ? cornerRadius : 0.f},
{tr ? cornerRadius : 0.f, tr ? cornerRadius : 0.f},
{br ? cornerRadius : 0.f, br ? cornerRadius : 0.f},
{bl ? cornerRadius : 0.f, bl ? cornerRadius : 0.f}
};
return SkRRect::MakeRectRadii(baseRect, radii);
};
// Test all combinations of circular corners
SkRRect rrects[] = {
makeRRect(false, false, false, false),
makeRRect(true, false, false, false),
makeRRect(false, true, false, false),
makeRRect(false, false, true, false),
makeRRect(false, false, false, true),
makeRRect(true, true, false, false),
makeRRect(true, false, true, false),
makeRRect(true, false, false, true),
makeRRect(false, true, true, false),
makeRRect(false, true, false, true),
makeRRect(false, false, true, true),
makeRRect(true, true, true, false),
makeRRect(true, true, false, true),
makeRRect(true, false, true, true),
makeRRect(false, true, true, true),
makeRRect(true, true, true, true)
};
std::pair<SkPoint, SkMatrix> transforms[] = {
// Identity (top-left grid)
{{0.f, 0.f}, SkMatrix()},
// Non-uniform scale (top-right grid)
{{160.f, 0.f}, SkMatrix::Scale(1.2f, 0.8f)},
// Orthgonal (bot-left grid)
{{20.f, 160.f}, SkMatrix::RotateDeg(10.f, {2 * baseRect.width(), 2 * baseRect.height()})},
// Fully affine (bot-right grid)
{{180.f, 140.f}, SkMatrix::Skew(0.2f, 0.1f)}
};
// Make this a complicated enough shape that Graphite doesn't just apply the clip geometrically.
SkPathBuilder b;
b.addRect(baseRect);
b.addRect(baseRect.makeInset(10, 10));
b.setFillType(SkPathFillType::kEvenOdd);
SkPath p = b.detach();
SkPaint fillPaint;
fillPaint.setColor(SK_ColorBLACK);
fillPaint.setAntiAlias(true);
for (auto [origin, xform] : transforms) {
canvas->save();
canvas->translate(origin.fX, origin.fY);
int x = 0;
int y = 0;
for (const SkRRect& clip : rrects) {
canvas->save();
canvas->concat(xform);
canvas->translate(5.f * (x + 1) + baseRect.width() * x,
5.f * (y + 1) + baseRect.height() * y);
canvas->clipRRect(clip, true);
canvas->drawPath(p, fillPaint);
canvas->restore();
x++;
if (x >= 4) {
x = 0;
y++;
}
}
canvas->restore();
}
}