tiny-skia-cpp
A C++20 2D rendering library (port of tiny-skia)
Loading...
Searching...
No Matches
Pipeline.h
1#pragma once
2
8
9#include <array>
10#include <cstddef>
11#include <cstdint>
12#include <vector>
13
14#include "tiny_skia/Transform.h"
15
16namespace tiny_skia {
17
18class Color;
19class PremultipliedColor;
20class PixmapView;
21class ScreenIntRect;
22struct MutableSubPixmapView;
23
25enum class SpreadMode {
26 Pad,
27 Reflect,
28 Repeat,
29};
30
32namespace pipeline {
33
35namespace highp {
36struct Pipeline;
37}
38
40namespace lowp {
41struct Pipeline;
42}
43
46enum class Stage : std::uint8_t {
47 MoveSourceToDestination,
48 MoveDestinationToSource,
49 Clamp0,
50 ClampA,
51 Premultiply,
52 UniformColor,
53 SeedShader,
54 LoadDestination,
55 Store,
56 LoadDestinationU8,
57 StoreU8,
58 Gather,
59 LoadMaskU8,
60 MaskU8,
61 ScaleU8,
62 LerpU8,
63 Scale1Float,
64 Lerp1Float,
73 Clear,
76 Plus,
77 Screen,
78 Xor,
81 Darken,
85 Lighten,
86 Overlay,
88 Hue,
90 Color,
92 SourceOverRgba,
93 Transform,
94 Reflect,
95 Repeat,
97 Bicubic,
98 PadX1,
99 ReflectX1,
100 RepeatX1,
101 Gradient,
102 EvenlySpaced2StopGradient,
103 XYToUnitAngle,
104 XYToRadius,
105 XYTo2PtConicalFocalOnCircle,
106 XYTo2PtConicalWellBehaved,
107 XYTo2PtConicalSmaller,
108 XYTo2PtConicalGreater,
109 XYTo2PtConicalStrip,
110 Mask2PtConicalNan,
111 Mask2PtConicalDegenerates,
112 ApplyVectorMask,
113 Alter2PtConicalCompensateFocal,
114 Alter2PtConicalUnswap,
115 NegateX,
116 ApplyConcentricScaleBias,
117 GammaExpand2,
118 GammaExpandDestination2,
119 GammaCompress2,
120 GammaExpand22,
121 GammaExpandDestination22,
122 GammaCompress22,
123 GammaExpandSrgb,
124 GammaExpandDestinationSrgb,
125 GammaCompressSrgb,
126 // Highp-only stages for unpremultiplied output (matching Skia's kUnpremul output).
127 Unpremultiply,
128 PremultiplyDestination,
129 // Fused stages for performance.
130 FusedLinearGradient2Stop,
131 FusedRadialGradient2Stop,
132 FusedBilinearPattern,
133};
134
136inline constexpr std::size_t kStagesCount = 1 + static_cast<std::size_t>(Stage::FusedBilinearPattern);
138inline constexpr std::size_t kMaxStages = 32;
139
141struct AAMaskCtx {
142 std::array<std::uint8_t, 2> pixels = {0, 0};
143 std::uint32_t stride = 0;
144 std::size_t shift = 0;
145
146 [[nodiscard]] std::array<std::uint8_t, 2> copyAtXY(std::size_t dx, std::size_t dy,
147 std::size_t tail) const {
148 const auto base = static_cast<std::size_t>(stride) * dy + dx;
149 if (base < shift) {
150 return {0, 0};
151 }
152 const auto offset = base - shift;
153 if (offset == 0 && tail == 1) {
154 return {pixels[0], 0};
155 }
156 if (offset == 0 && tail == 2) {
157 return {pixels[0], pixels[1]};
158 }
159 if (offset == 1 && tail == 1) {
160 return {pixels[1], 0};
161 }
162 return {0, 0};
163 }
164};
165
167struct MaskCtx {
168 const std::uint8_t* data = nullptr;
169 std::uint32_t realWidth = 0;
170
171 [[nodiscard]] std::size_t byteOffset(std::size_t dx, std::size_t dy) const {
172 return offset(dx, dy);
173 }
174
175 private:
176 [[nodiscard]] constexpr std::size_t offset(std::size_t dx, std::size_t dy) const {
177 return static_cast<std::size_t>(realWidth) * dy + dx;
178 }
179};
180
182struct SamplerCtx {
183 SpreadMode spreadMode = SpreadMode::Pad;
184 float invWidth = 0.0f;
185 float invHeight = 0.0f;
186};
187
189struct UniformColorCtx {
190 float r = 0.0f;
191 float g = 0.0f;
192 float b = 0.0f;
193 float a = 0.0f;
194 std::array<std::uint16_t, 4> rgba = {0, 0, 0, 0};
195};
196
198struct GradientColor {
199 float r = 0.0f;
200 float g = 0.0f;
201 float b = 0.0f;
202 float a = 0.0f;
203
204 constexpr bool operator==(const GradientColor&) const = default;
205
206 [[nodiscard]] static constexpr GradientColor newFromRGBA(float r, float g, float b, float a) {
207 return GradientColor{r, g, b, a};
208 }
209};
210
212struct EvenlySpaced2StopGradientCtx {
213 GradientColor factor{};
214 GradientColor bias{};
215};
216
220struct FusedLinearGradient2StopCtx {
221 float sx = 0.0f;
222 float kx = 0.0f;
223 float tx = 0.0f;
224 GradientColor factor{};
225 GradientColor bias{};
226 bool needsPremultiply = false;
227};
228
232struct FusedRadialGradient2StopCtx {
233 float sx = 0.0f;
234 float kx = 0.0f;
235 float tx = 0.0f;
236 float ky = 0.0f;
237 float sy = 0.0f;
238 float ty = 0.0f;
239 GradientColor factor{};
240 GradientColor bias{};
241 bool needsPremultiply = false;
242};
243
247struct FusedBilinearPatternCtx {
248 float sx = 0.0f;
249 float kx = 0.0f;
250 float tx = 0.0f;
251 float ky = 0.0f;
252 float sy = 0.0f;
253 float ty = 0.0f;
254 const std::uint8_t* pixels = nullptr;
255 std::uint32_t width = 0;
256 std::uint32_t height = 0;
257 float invWidth = 0.0f;
258 float invHeight = 0.0f;
259 SpreadMode spreadMode = SpreadMode::Pad;
260 float opacity = 1.0f;
261 bool useNearest = false;
262 bool fuseSourceOver = false;
263 bool fuseSourceOverCoverage = false;
264 std::int8_t opaqueCheckResult = -1;
265};
266
268struct TwoPointConicalGradientCtx {
269 std::array<std::uint32_t, 8> mask = {};
270 float p0 = 0.0f;
271 float p1 = 0.0f;
272};
273
275struct TileCtx {
276 float scale = 0.0f;
277 float invScale = 0.0f;
278};
279
281struct Context {
282 float currentCoverage = 0.0f;
283 SamplerCtx sampler;
284 UniformColorCtx uniformColor;
285 EvenlySpaced2StopGradientCtx evenlySpaced2StopGradient;
286 FusedLinearGradient2StopCtx fusedLinearGradient2Stop;
287 FusedRadialGradient2StopCtx fusedRadialGradient2Stop;
288 FusedBilinearPatternCtx fusedBilinearPattern;
289 struct GradientCtx {
290 std::size_t len = 0;
291 std::vector<GradientColor> factors;
292 std::vector<GradientColor> biases;
293 std::vector<float> tValues;
294
295 void pushConstColor(GradientColor color) {
296 factors.push_back(GradientColor{0.0f, 0.0f, 0.0f, 0.0f});
297 biases.push_back(color);
298 }
299 } gradient;
300
301 TwoPointConicalGradientCtx twoPointConicalGradient;
302 TileCtx limitX;
303 TileCtx limitY;
304 Transform transform;
305};
306
308class RasterPipeline {
309 public:
310 enum class Kind {
311 High,
312 Low,
313 };
314
315 RasterPipeline() = default;
316 RasterPipeline(Kind kind, Context context, const std::array<Stage, kMaxStages>& stages,
317 std::size_t stageCount);
318
319 [[nodiscard]] Kind kind() const { return kind_; }
320
321 Context& ctx() { return ctx_; }
322 [[nodiscard]] const Context& ctx() const { return ctx_; }
323
324 void run(const ScreenIntRect& rect, const AAMaskCtx& aaMaskCtx, MaskCtx maskCtx,
325 const PixmapView& pixmapSrc, MutableSubPixmapView* pixmapDst);
326
327 [[nodiscard]] std::size_t stageCount() const { return stageCount_; }
328
329 private:
330 using HighpStageFn = void (*)(highp::Pipeline&);
331 using LowpStageFn = void (*)(lowp::Pipeline&);
332
333 void initializeFunctions();
334
335 Kind kind_ = Kind::High;
336 Context ctx_{};
337 std::array<Stage, kMaxStages> stages_ = {};
338 std::size_t stageCount_ = 0;
339 std::array<HighpStageFn, kMaxStages> highpFunctions_{};
340 std::array<HighpStageFn, kMaxStages> highpTailFunctions_{};
341 std::array<LowpStageFn, kMaxStages> lowpFunctions_{};
342 std::array<LowpStageFn, kMaxStages> lowpTailFunctions_{};
343};
344
346class RasterPipelineBuilder {
347 public:
348 RasterPipelineBuilder() = default;
349
350 void setForceHqPipeline(bool hq) { forceHqPipeline_ = hq; }
351
352 void push(Stage stage) {
353 if (stageCount_ >= kMaxStages) {
354 return;
355 }
356 stages_[stageCount_++] = stage;
357 }
358
359 void pushTransform(const Transform& ts) {
360 if (ts.isFinite() && !ts.isIdentity()) {
361 push(Stage::Transform);
362 ctx_.transform = ts;
363 }
364 }
365
366 void pushUniformColor(const PremultipliedColor& c);
367
368 [[nodiscard]] RasterPipeline compile();
369
370 [[nodiscard]] Context& ctx() { return ctx_; }
371 [[nodiscard]] const Context& ctx() const { return ctx_; }
372
373 private:
374 std::array<Stage, kMaxStages> stages_ = {};
375 std::size_t stageCount_ = 0;
376 bool forceHqPipeline_ = false;
377 Context ctx_;
378};
379
380} // namespace pipeline
381
382} // namespace tiny_skia
@ SoftLight
Soft version of hard light.
@ Lighten
Maximum of source and destination.
@ Exclusion
Similar to Difference but lower contrast.
@ Difference
Absolute difference.
@ Saturation
Source saturation, destination hue and luminosity.
@ Screen
Inverse multiply.
@ Plus
Sum (clamped).
@ SourceOut
Source where destination is transparent.
@ DestinationOut
Destination where source is transparent.
@ DestinationIn
Destination where source is opaque.
@ Luminosity
Source luminosity, destination hue and saturation.
@ Overlay
Multiply or screen based on destination.
@ SourceIn
Source where destination is opaque.
@ Xor
Source XOR destination.
@ DestinationOver
Destination over source.
@ SourceAtop
Source atop destination.
@ DestinationAtop
Destination atop source.
@ ColorBurn
Darken destination toward source.
@ SourceOver
Source over destination (default).
@ Modulate
Component-wise multiply.
@ Color
Source hue and saturation, destination luminosity.
@ HardLight
Multiply or screen based on source.
@ Clear
Output is transparent.
@ Multiply
Component-wise multiply (with alpha handling).
@ ColorDodge
Brighten destination toward source.
@ Darken
Minimum of source and destination.
@ Hue
Source hue, destination saturation and luminosity.
@ Bicubic
Bicubic interpolation (highest quality).
@ Bilinear
Bilinear interpolation.
2D affine transformation matrix.