Skip to content

Commit

Permalink
Merge pull request #267 from parasol-framework/test/svg
Browse files Browse the repository at this point in the history
[SVG] Added ENFORCE_TRACKING flag
  • Loading branch information
paul-manias authored Oct 14, 2024
2 parents 7b7b1e3 + b6e9887 commit 09cb770
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 10 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ else ()
endif ()
option (BUILD_TESTS "Build/enable tests" ON)
option (BUILD_DEFS "Auto-generate C/C++ headers and documentation" OFF)
option (DISABLE_SSL "Disable built-in SSL support even if available on this system" OFF)
option (DISABLE_SSL "Disable built-in SSL support even if available on this system" ON)
option (DISABLE_X11 "Disable X11 even if available on this system" OFF)
option (DISABLE_AUDIO "Disable audio API" OFF)
option (DISABLE_DISPLAY "Disable display API" OFF)
Expand Down
5 changes: 3 additions & 2 deletions docs/xml/modules/classes/svg.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

<method>
<name>Render</name>
<comment>Render the scene to a target Bitamp.</comment>
<comment>Render the scene to a target Bitmap.</comment>
<prototype>ERR svg::Render(OBJECTPTR Object, objBitmap * Bitmap, LONG X, LONG Y, LONG Width, LONG Height)</prototype>
<input>
<param type="objBitmap *" name="Bitmap">The target <class name="Bitmap">Bitmap</class>.</param>
Expand Down Expand Up @@ -200,7 +200,7 @@
<description>
<p>During the normal initialisation process, a new <class name="VectorViewport">VectorViewport</class> is created to host the SVG scene graph. By default, the viewport and its content is strictly owned by the SVG object unless a Target is defined to redirect the scene graph elsewhere.</p>
<p>The provided Target can be any object class, as long as it forms part of a scene graph owned by a <class name="VectorScene">VectorScene</class> object. It is recommended that the chosen target is a <class name="VectorViewport">VectorViewport</class>.</p>
<p>The use of a Target will make the generated scene graph independent of the SVG object. Consequently, it is possible to terminate the SVG object without impacting the resources it created.</p>
<p>The use of a Target will make the generated scene graph independent of the SVG object. Consequently, it is possible to terminate the SVG object without impacting the resources it created. If tracking back to the SVG object is still required, use the <code>ENFORCE_TRACKING</code> option in <fl>Flags</fl> to ensure that SVG definitions are still terminated on object destruction.</p>
</description>
</field>

Expand Down Expand Up @@ -229,6 +229,7 @@
<constants lookup="SVF" comment="SVG flags.">
<const name="ALPHA">Generate an alpha channel in the rendered image.</const>
<const name="AUTOSCALE">In auto-resize mode, vector dimensions are scaled to the width and height of the vector page. The <class name="VectorScene" field="PageWidth">VectorScene.PageWidth</class> and <class name="VectorScene" field="PageHeight">VectorScene.PageHeight</class> must be set for this.</const>
<const name="ENFORCE_TRACKING">Enforce tracking of definition objects when a Target is used.</const>
</constants>

</types>
Expand Down
1 change: 1 addition & 0 deletions include/parasol/modules/svg.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum class SVF : ULONG {
NIL = 0,
AUTOSCALE = 0x00000001,
ALPHA = 0x00000002,
ENFORCE_TRACKING = 0x00000004,
};

DEFINE_ENUM_FLAG_OPERATORS(SVF)
Expand Down
2 changes: 1 addition & 1 deletion src/core/lib_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@ void NotifySubscribers(OBJECTPTR Object, AC ActionID, APTR Parameters, ERR Error
glSubReadOnly--;

if (!glSubReadOnly) {
if (!glDelayedSubscribe.empty()) {
if (!glDelayedSubscribe.empty()) { // Check if SubscribeAction() was called during the notification process
for (auto &entry : glDelayedSubscribe) {
glSubscriptions[entry.ObjectID][LONG(entry.ActionID)].emplace_back(entry.Callback.Context, entry.Callback.Routine, entry.Callback.Meta);
}
Expand Down
2 changes: 1 addition & 1 deletion src/picture/picture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,10 @@ static ERR PICTURE_Activate(extPicture *Self)

static ERR PICTURE_Free(extPicture *Self)
{
Self->~extPicture();
if (Self->prvFile) { FreeResource(Self->prvFile); Self->prvFile = NULL; }
if (Self->Bitmap) { FreeResource(Self->Bitmap); Self->Bitmap = NULL; }
if (Self->Mask) { FreeResource(Self->Mask); Self->Mask = NULL; }
Self->~extPicture();
return ERR::Okay;
}

Expand Down
12 changes: 9 additions & 3 deletions src/svg/class_svg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ static ERR SVG_DataFeed(extSVG *Self, struct acDataFeed *Args)

static ERR SVG_Free(extSVG *Self)
{
Self->~extSVG();

if (Self->AnimationTimer) {
UpdateTimer(Self->AnimationTimer, 0);
Self->AnimationTimer = 0;
Expand All @@ -108,6 +106,12 @@ static ERR SVG_Free(extSVG *Self)
if (Self->Statement) { FreeResource(Self->Statement); Self->Statement = NULL; }
if (Self->XML) { FreeResource(Self->XML); Self->XML = NULL; }

if (!Self->Resources.empty()) {
for (auto id : Self->Resources) FreeResource(id);
}

Self->~extSVG();

return ERR::Okay;
}

Expand Down Expand Up @@ -552,7 +556,9 @@ The provided Target can be any object class, as long as it forms part of a scene
object. It is recommended that the chosen target is a @VectorViewport.
The use of a Target will make the generated scene graph independent of the SVG object. Consequently, it is possible
to terminate the SVG object without impacting the resources it created.
to terminate the SVG object without impacting the resources it created. If tracking back to the SVG object is
still required, use the `ENFORCE_TRACKING` option in #Flags to ensure that SVG definitions are still terminated on
object destruction.
*********************************************************************************************************************/

Expand Down
1 change: 1 addition & 0 deletions src/svg/class_svg_def.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
static const struct FieldDef clSVGFlags[] = {
{ "Autoscale", 0x00000001 },
{ "Alpha", 0x00000002 },
{ "EnforceTracking", 0x00000004 },
{ NULL, 0 }
};

Expand Down
5 changes: 5 additions & 0 deletions src/svg/gradients.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ static ERR xtag_lineargradient(extSVG *Self, const XMLTag &Tag)
if (!id.empty()) {
SetName(gradient, id.c_str());
add_id(Self, Tag, id);
track_object(Self, gradient);
return Self->Scene->addDef(id.c_str(), gradient);
}
else return ERR::Okay;
Expand Down Expand Up @@ -222,6 +223,7 @@ static ERR xtag_radialgradient(extSVG *Self, const XMLTag &Tag)
if (!id.empty()) {
SetName(gradient, id.c_str());
add_id(Self, Tag, id);
track_object(Self, gradient);
return Self->Scene->addDef(id.c_str(), gradient);
}
else return ERR::Okay;
Expand Down Expand Up @@ -291,6 +293,7 @@ static ERR xtag_diamondgradient(extSVG *Self, const XMLTag &Tag)
if (!id.empty()) {
SetName(gradient, id.c_str());
add_id(Self, Tag, id);
track_object(Self, gradient);
return Self->Scene->addDef(id.c_str(), gradient);
}
else return ERR::Okay;
Expand Down Expand Up @@ -358,6 +361,7 @@ static ERR xtag_contourgradient(extSVG *Self, const XMLTag &Tag)
if (!id.empty()) {
SetName(gradient, id.c_str());
add_id(Self, Tag, id);
track_object(Self, gradient);
return Self->Scene->addDef(id.c_str(), gradient);
}
else return ERR::Okay;
Expand Down Expand Up @@ -431,6 +435,7 @@ static ERR xtag_conicgradient(extSVG *Self, const XMLTag &Tag)
if (!id.empty()) {
SetName(gradient, id.c_str());
add_id(Self, Tag, id);
track_object(Self, gradient);
return Self->Scene->addDef(id.c_str(), gradient);
}
else return ERR::Okay;
Expand Down
8 changes: 8 additions & 0 deletions src/svg/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ static void xtag_pathtransition(extSVG *Self, XMLTag &Tag)

if (InitObject(trans) IS ERR::Okay) {
if (!Self->Cloning) Self->Scene->addDef(id.c_str(), trans);
track_object(Self, trans);
return;
}
}
Expand Down Expand Up @@ -266,6 +267,7 @@ static void xtag_clippath(extSVG *Self, XMLTag &Tag)
process_children(Self, state, Tag, vp);

Self->Scene->addDef(id.c_str(), clip);
track_object(Self, clip);
}
else FreeResource(clip);
}
Expand Down Expand Up @@ -339,6 +341,7 @@ static void xtag_mask(extSVG *Self, XMLTag &Tag)
process_children(Self, state, Tag, vp);

Self->Scene->addDef(id.c_str(), clip);
track_object(Self, clip);
}
else FreeResource(clip);
}
Expand Down Expand Up @@ -1466,6 +1469,8 @@ static void xtag_filter(extSVG *Self, svgState &State, XMLTag &Tag)
Self->Effects.clear();

if (!Self->Cloning) Self->Scene->addDef(id.c_str(), filter);

track_object(Self, filter);
}
else FreeResource(filter);
}
Expand Down Expand Up @@ -1560,6 +1565,7 @@ static void process_pattern(extSVG *Self, XMLTag &Tag)
if (!Self->Cloning) {
add_id(Self, Tag, id);
Self->Scene->addDef(id.c_str(), pattern);
track_object(Self, pattern);
}
}
else {
Expand Down Expand Up @@ -1812,6 +1818,7 @@ static void def_image(extSVG *Self, XMLTag &Tag)
if (!Self->Cloning) {
add_id(Self, Tag, id);
Self->Scene->addDef(id.c_str(), image);
track_object(Self, image);
}
}
else {
Expand Down Expand Up @@ -1896,6 +1903,7 @@ static ERR xtag_image(extSVG *Self, svgState &State, XMLTag &Tag, OBJECTPTR Pare
SetOwner(pic, image); // It's best if the pic belongs to the image.

Self->Scene->addDef(id.c_str(), image);
track_object(Self, image);
}
else return ERR::CreateObject;
}
Expand Down
8 changes: 8 additions & 0 deletions src/svg/svg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class extSVG : public objSVG {
std::map<OBJECTID, svgAnimState> Animatrix; // For animated transforms, a vector may have one matrix only.
std::vector<std::unique_ptr<svgLink>> Links;
std::vector<svgInherit> Inherit;
std::vector<OBJECTID> Resources; // Resources to terminate if ENFORCE_TRACKING was enabled.
std::map<ULONG, std::vector<anim_base *>> StartOnBegin; // When the animation indicated by ULONG begins, it must activate() the referenced anim_base
std::map<ULONG, std::vector<anim_base *>> StartOnEnd; // When the animation indicated by ULONG ends, it must activate() the referenced anim_base
TIMER AnimationTimer;
Expand Down Expand Up @@ -159,6 +160,13 @@ static void xtag_use(extSVG *, svgState &, XMLTag &, OBJECTPTR);
static ERR xtag_style(extSVG *, XMLTag &);
static void xtag_symbol(extSVG *, XMLTag &);

inline void track_object(extSVG *SVG, OBJECTPTR Object)
{
if ((SVG->Flags & SVF::ENFORCE_TRACKING) != SVF::NIL) {
SVG->Resources.emplace_back(Object->UID);
}
}

//********************************************************************************************************************

#include "funit.cpp"
Expand Down
3 changes: 2 additions & 1 deletion src/svg/svg.fdl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
module({ name="SVG", copyright="Paul Manias © 2010-2024", version=1.0, timestamp=20240611 }, function()
flags("SVF", { comment="SVG flags." },
"AUTOSCALE: In auto-resize mode, vector dimensions are scaled to the width and height of the vector page. The @VectorScene.PageWidth and @VectorScene.PageHeight must be set for this.",
"ALPHA: Generate an alpha channel in the rendered image.")
"ALPHA: Generate an alpha channel in the rendered image.",
"ENFORCE_TRACKING: Enforce tracking of definition objects when a Target is used.")

methods("svg", "Svg", {
{ id=1, name="Render" },
Expand Down
2 changes: 1 addition & 1 deletion src/svg/svg_def.c
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#undef MOD_IDL
#define MOD_IDL "c.SVF:ALPHA=0x2,AUTOSCALE=0x1\n"
#define MOD_IDL "c.SVF:ALPHA=0x2,AUTOSCALE=0x1,ENFORCE_TRACKING=0x4\n"

0 comments on commit 09cb770

Please sign in to comment.