2424#include < unordered_set>
2525#include < vector>
2626#include " pagx/FontConfig.h"
27+ #include " pagx/ImageResourceProvider.h"
2728#include " pagx/nodes/Animation.h"
2829#include " pagx/nodes/Layer.h"
2930#include " pagx/nodes/Node.h"
@@ -33,6 +34,8 @@ namespace pagx {
3334
3435class LayoutContext ;
3536class PAGScene ;
37+ class Image ;
38+ class ImagePattern ;
3639
3740/* *
3841 * PAGXDocument is the root container for a PAGX document.
@@ -126,7 +129,9 @@ class PAGXDocument : public Node {
126129
127130 /* *
128131 * Returns a list of external file paths referenced by Image nodes or external composition layers
129- * that have no embedded data. Data URIs (paths starting with "data:") are excluded.
132+ * that have no embedded data. Data URIs (paths starting with "data:") are excluded. Image nodes
133+ * for which the current ImageResourceProvider already holds a decoded counterpart are also
134+ * excluded so the same resource is not fetched twice.
130135 */
131136 std::vector<std::string> getExternalFilePaths () const ;
132137
@@ -143,6 +148,17 @@ class PAGXDocument : public Node {
143148 */
144149 bool loadFileData (const std::string& filePath, std::shared_ptr<Data> data);
145150
151+ /* *
152+ * Sets the image resource provider used by the rendering pipeline to resolve pre-decoded images.
153+ * When set, getExternalFilePaths() consults the provider to exclude paths that already have a
154+ * decoded counterpart. The renderer queries the provider during layer building via
155+ * resolveImage().
156+ *
157+ * Passing nullptr removes the provider; the renderer will use only embedded data / file paths.
158+ * @param provider the platform-specific image resource provider, or nullptr to remove.
159+ */
160+ void setImageResourceProvider (std::shared_ptr<ImageResourceProvider> provider);
161+
146162 /* *
147163 * Executes auto layout on the document, positioning layers according to their layout
148164 * constraints. Must be called before rendering or font embedding. Re-running layout on an
@@ -234,6 +250,9 @@ class PAGXDocument : public Node {
234250
235251 private:
236252 PAGXDocument () = default ;
253+
254+ const std::vector<const Layer*>& findLayersByImageFilePath (const std::string& imageFilePath);
255+
237256 // Recursive layout worker. visited holds the documents on the current ancestor path so an
238257 // externalDoc cycle built directly through the API (bypassing loadFileData's own chain guard)
239258 // is detected and stops the recursion instead of overflowing the stack.
@@ -247,6 +266,7 @@ class PAGXDocument : public Node {
247266 void registerLiveScene (const std::shared_ptr<PAGScene>& scene);
248267 void unregisterLiveScene (PAGScene* scene);
249268
269+ std::shared_ptr<ImageResourceProvider> _imageResourceProvider = nullptr ;
250270 FontConfig fontConfig;
251271 bool layoutApplied = false ;
252272 std::unordered_map<std::string, Node*> nodeMap = {};
@@ -257,11 +277,20 @@ class PAGXDocument : public Node {
257277 // does not keep PAGScene alive; expired entries are pruned during notifyChange.
258278 std::vector<std::weak_ptr<PAGScene>> liveScenes = {};
259279
280+ // Lazily built index of Image node filePath -> pagx Layer list, used by
281+ // findLayersByImageFilePath(). Built on first query; invalidated by notifyChange() since edits
282+ // may alter the tree topology or Image node filePath values. Also freed when the document is
283+ // destroyed (on the next parsePAGX() call).
284+ std::unordered_map<std::string, std::vector<const Layer*>> layersByImageFilePath = {};
285+ bool layersByImageFilePathBuilt = false ;
286+
260287 friend class PAGXImporter ;
261288 friend class PAGXExporter ;
262289 friend class TextLayoutContext ;
263290 friend class PAGScene ;
264291 friend class PAGComposition ;
292+ friend class LayerBuilderContext ;
293+ friend class LayerBuilderSession ;
265294};
266295
267296} // namespace pagx
0 commit comments