#pragma once #include "Document/DocumentLimits.h" #include "Document/LayerAdjustment.h" #include "Document/LayerAppearance.h" #include #include #include #include #include #include #include #include // Per-render dependency cache: a layer shows through its source's alpha. class LiveMaskRenderer { public: static constexpr qint64 pixelBudget = DocumentLimits::maxSurfacePixels; using Source = std::function(QUuid)>; // Draws a layer through `clip`: device-sized coverage, null for none. using DrawOwn = std::function; LiveMaskRenderer(Source source, DrawOwn drawOwn, qint64 pixelBudget = LiveMaskRenderer::pixelBudget); // Clipping stacks share the base's alpha instead of repainting it. void prepareStacks(const std::vector &ids, const std::function(QUuid)> &parent, const std::function &blend); void drawComposite(QUuid id, QPainter &context, const QImage &clip = QImage()); void draw(QUuid id, QPainter &context, const QImage &clip = QImage()); // An adjustment layer's settings, opacity and own mask as coverage. std::function(QUuid)> adjustment = [](QUuid) { return std::optional(); }; std::function adjustmentOpacity = [](QUuid) { return 1.0; }; std::function adjustmentClip = [](QUuid, const QPainter &, QImage &) {}; // Painter units a document pixel: the canvas's zoom. double adjustmentScale = 1; // The document a painter region shows: the canvas maps it. std::function adjustmentRegion; private: // The pixels beneath, adjusted and mixed back through coverage. void adjust(QUuid id, QPainter &context, const QImage &clip); // A layer's alpha through its own source; nil on failure. std::optional coverage(QUuid id, const QPainter &context); bool fits(const QPainter &context) const; const Source m_source; const DrawOwn m_drawOwn; const qint64 m_pixelBudget; // Standard containers: Qt 6.4's hash inserts terminate out of memory. std::map m_cache; std::set m_visiting; std::map> m_stacks; std::set m_stacked; std::map m_stackModes; // Every prepared layer's mode, as Swift's `blendMode`. std::map m_modes; };