Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
box_shadow_cache.hpp
Go to the documentation of this file.
1#pragma once
2
24
25#ifdef PULP_HAS_SKIA
26
27#include <cmath>
28#include <cstddef>
29#include <cstdint>
30#include <functional>
31
32#include "include/core/SkRefCnt.h"
33
34class SkImage;
35
36#include <pulp/canvas/canvas.hpp> // Color (for the test-render helper)
37
38namespace pulp::canvas {
39
42struct BoxShadowKey {
43 std::int32_t w = 0;
44 std::int32_t h = 0;
45 std::int32_t dx = 0;
46 std::int32_t dy = 0;
47 std::int32_t blur = 0;
48 std::int32_t spread = 0;
49 std::int32_t corner_radius = 0;
50 std::int32_t scale = 0;
51
52 bool operator==(const BoxShadowKey& o) const noexcept {
53 return w == o.w && h == o.h && dx == o.dx && dy == o.dy &&
54 blur == o.blur && spread == o.spread &&
55 corner_radius == o.corner_radius && scale == o.scale;
56 }
57
58 static std::int32_t q(float v) noexcept {
59 // static_cast<int32_t> of a non-finite or out-of-range float is UB, and
60 // a parsed/animated shadow param can reach inf/NaN. Map non-finite to a
61 // fixed bucket and clamp so the *4 and the cast can't overflow int32.
62 if (!std::isfinite(v)) return 0;
63 constexpr float kLimit = 4.0e8f; // *4 ≈ 1.6e9, well inside int32 range
64 if (v > kLimit) v = kLimit;
65 else if (v < -kLimit) v = -kLimit;
66 return static_cast<std::int32_t>(v * 4.0f + (v < 0 ? -0.5f : 0.5f));
67 }
68};
69
70class BoxShadowCache {
71public:
72 static BoxShadowCache& instance();
73
76 sk_sp<SkImage> get_or_render(const BoxShadowKey& key,
77 const std::function<sk_sp<SkImage>()>& render);
78
79 struct Stats {
80 std::uint64_t hits = 0;
81 std::uint64_t renders = 0;
82 std::size_t size = 0;
83 };
84 Stats stats() const;
85 void reset_stats();
86 void clear();
87
90 void set_enabled(bool enabled);
91 bool enabled() const;
92
93 void set_capacity(std::size_t capacity);
94
95private:
96 BoxShadowCache() = default;
97 struct Impl;
98 // Defined in box_shadow_cache.cpp; stateful members live there to keep this
99 // header free of <mutex>/<list>/<unordered_map>.
100 static Impl& impl();
101};
102
103// ── Test-only render helper ─────────────────────────────────────────────────
104// Renders a single box shadow into an RGBA8888 (unpremultiplied) raster buffer
105// of px_w x px_h via the real SkiaCanvas path, so tests can pixel-compare the
106// cached vs. uncached output without including Skia headers themselves. Returns
107// the pixel buffer (size px_w*px_h*4).
108std::vector<std::uint8_t> render_box_shadow_to_rgba(
109 int px_w, int px_h, float scale,
110 float x, float y, float w, float h,
111 float dx, float dy, float blur, float spread,
112 Color color, float corner_radius, bool inset);
113
114} // namespace pulp::canvas
115
116#endif // PULP_HAS_SKIA
Definition affine_transform.hpp:24
@ spread
Definition voicing.hpp:23
@ size
Definition config.hpp:216
@ o
Definition formant_filter_bank.hpp:20
bool operator==(const ModalSpec &a, const ModalSpec &b)
Exact equality over every known field.
void scale(const float *a, float scalar, float *dst, std::size_t count) noexcept
@ h
Definition input_events.hpp:39
@ q
Definition input_events.hpp:41
@ v
Definition input_events.hpp:41
@ w
Definition input_events.hpp:41
Definition canvas.hpp:52