blob: 99350efe7179a901002a0fe333aad144a91641f9 [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.
*/
#ifndef skgpu_graphite_sparse_strips_CullingRepros_DEFINED
#define skgpu_graphite_sparse_strips_CullingRepros_DEFINED
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkRect.h"
#include "src/core/SkFloatBits.h"
namespace skgpu::graphite::CullingRepros {
// The inputs of a single sparse strips draw: its path, transform, and device space clip.
struct Repro {
SkPath fPath;
SkMatrix fCtm;
SkIRect fClip;
};
// A contour whose verbs lie entirely above, right of, and below `clip` (in that order), so Flatten
// culls all of them. Its closing edge runs down the left of the clip and is the only geometry that
// contributes winding inside it. The path covers the entire clip.
//
// Note: With `close`, SkPath::Iter emits the closing edge as a line verb, which Flatten never
// culls. Only the open (implicitly closed) form exercises Flatten's handling of the closing edge.
inline SkPath AllVerbsCulledContour(const SkIRect& clip, bool close) {
const float l = static_cast<float>(clip.fLeft);
const float t = static_cast<float>(clip.fTop);
const float r = static_cast<float>(clip.fRight);
const float b = static_cast<float>(clip.fBottom);
SkPathBuilder builder;
builder.moveTo(l - 10.0f, t - 20.0f)
.quadTo((l + r) * 0.5f, t - 60.0f, r + 20.0f, t - 20.0f) // Above
.conicTo(r + 60.0f, (t + b) * 0.5f, r + 20.0f, b + 20.0f, 0.7f) // Right
.cubicTo(r, b + 60.0f, l, b + 60.0f, l - 12.0f, b + 20.0f); // Below
if (close) {
builder.close();
}
return builder.detach();
}
// A draw captured from desk_tiger8svg.skp in the viewer, zoomed in far enough that it lies entirely
// outside of the clip. Its four cubics are culled (above, above, right, below), and the implicit
// closing edge runs down the left of the clip, covering all of it. Flatten used to drop the closing
// edge because no verb in the contour survived culling, leaving the clip unfilled.
inline Repro DeskTiger8Capture3Draw2() {
SkPathBuilder builder(SkPathFillType::kWinding);
builder.moveTo(SkBits2Float(0x43e93333), SkBits2Float(0x44059333)); // 466.4, 534.3
builder.cubicTo(SkBits2Float(0x43e93333), SkBits2Float(0x44059333),
SkBits2Float(0x43ebc000), SkBits2Float(0x4400cccd),
SkBits2Float(0x43f68ccd), SkBits2Float(0x44017333));
builder.cubicTo(SkBits2Float(0x43f68ccd), SkBits2Float(0x44017333),
SkBits2Float(0x43fdc000), SkBits2Float(0x44018ccd),
SkBits2Float(0x4400199a), SkBits2Float(0x44055999));
builder.cubicTo(SkBits2Float(0x44007334), SkBits2Float(0x44066ccc),
SkBits2Float(0x44009334), SkBits2Float(0x44080666),
SkBits2Float(0x44000ccd), SkBits2Float(0x44097fff));
builder.cubicTo(SkBits2Float(0x44000ccd), SkBits2Float(0x44097fff),
SkBits2Float(0x43fdc000), SkBits2Float(0x440d1999),
SkBits2Float(0x43f5199a), SkBits2Float(0x440cc665));
// [379.604 0 -190171 | 0 379.604 -204002 | 0 0 1]
const SkMatrix ctm = SkMatrix::MakeAll(
SkBits2Float(0x43bdcd5e), SkBits2Float(0x00000000), SkBits2Float(0xc839b6c7),
SkBits2Float(0x00000000), SkBits2Float(0x43bdcd5e), SkBits2Float(0xc8473891),
SkBits2Float(0x00000000), SkBits2Float(0x00000000), SkBits2Float(0x3f800000));
return {builder.detach(), ctm, SkIRect::MakeLTRB(0, 0, 2560, 1410)};
}
} // namespace skgpu::graphite::CullingRepros
#endif // skgpu_graphite_sparse_strips_CullingRepros_DEFINED