//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2010, 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available
// under the terms of the MIT License which is available at
// https://opensource.org/licenses/MIT
//
// SPDX-License-Identifier: MIT
//////////////////////////////////////////////////////////////////////////////

include::../_part_attributes.asciidoc[]
include::_local_attributes.asciidoc[]

:leveloffset: -2

[[lang-ref-svg-svgcopy]]
== CIF/SVG copy declarations

indexterm:[SVG copy declaration]
indexterm:[SVG,copy declaration]
indexterm:[SVG declaration,SVG copy declaration]
indexterm:[I/O declaration,SVG copy declaration]
indexterm:[see: svgcopy,SVG copy declaration]
A CIF/SVG copy declaration can be used to create copies of existing graphical elements of an SVG image.
This page explains the technical details of such copy declarations.
For concrete examples, see the <<lang-tut-svg-chapter-example-lamps,lamps example>> or the <<lang-tut-svg-chapter-example-buffers-products,buffers/products example>>.

indexterm:[SVG copy declaration,example]

=== Example

Consider the following SVG file:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/svgcopy.svg[]
----

It features three rectangles, with ids `rect`, `rect2`, and `rect3`, each with the same size.
They have different `fill` colors and positions.
The second rectangle is enclosed in a group with id `grp`.
Also consider the following CIF file:

[source, cif]
----
include::{incdir-lang-ref-svg}/svgcopy/svgcopy.cif[]
----

The effect of the copy declarations on the SVG image is:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/svgcopy.out.svg[]
----

indexterm:[SVG copy declaration,syntax]
indexterm:[SVG copy declaration,id]
indexterm:[SVG copy declaration,pre]
indexterm:[SVG copy declaration,prefix]
indexterm:[SVG copy declaration,post]
indexterm:[SVG copy declaration,postfix]
indexterm:[SVG copy declaration,file]

=== Syntax

The general syntax of CIF/SVG copy declarations is:

[source, cif]
----
svgcopy id <orig-elem-id> pre <prefix>;

svgcopy id <orig-elem-id> post <postfix>;

svgcopy id <orig-elem-id> pre <prefix> post <postfix>;

svgcopy id <orig-elem-id> pre <prefix> file "...";
----

The `svgcopy` keyword is followed by a specification of an SVG element <<lang-tut-svg-chapter-visualization-svg-id,id>>.
Every copy declaration must <<lang-ref-svg-svgout-id,specify the id>> of an SVG element, and an SVG element with that id must exist in the original SVG image, or must exist after applying one of the other copy declarations of the same CIF specification.
The `id` indicates the element that is to be copied.

The prefix and postfix are both optional, but at least one of them must be specified.
The prefix and postfix are used to generate unique ids for the copied elements.
The prefix (if any) is prepended to the ids of the copied elements, while the postfix (if any) is appended to the ids of the copied elements.
Prefixes (if specified) must be valid SVG name prefixes, which means they must be valid SVG names, just as <<lang-ref-svg-svgout-id,SVG element ids>>.
Similarly, postfixes (if specified) must be valid SVG name postfixes, which means they must be valid SVG names, but may start with dashes (`-`), dots (`.`), and numbers (`0` to `9`).
Similar to <<lang-ref-svg-svgout-id,ids>>, expressions may be used for both prefixes and postfixes, as long as they result in a `string` typed value when they're evaluated.

If we look at the rectangles example above, we see that the `rect` element is copied, and that the `id` of the copied element is prefixed with `a`, resulting in `arect` as `id` of the copy.
Similarly, `rect3` is prefixed with `+_+` and postfixed with `x` resulting in `+_rect3x+` as `id` of the copy.

The `grp` element is copied as well, with a `b` postfix.
This results in a copied group with `grpb` as its `id`.
Group `grp` also contains the rectangle with id `rect2`.
When an element is copied, all its contents are copied as well.
That is, the copy is recursive.
This means that the `rect2` element is copied as well, and that copy is also given a `b` postfix, resulting in `rect2b` as its `id`.

In the syntax examples above, we see that it is also allowed to declare a local <<lang-ref-svg-svgfile,SVG file declaration>>, that only applies to that specific copy declaration.

indexterm:[SVG copy declaration,placement]
indexterm:[SVG copy declaration,order]
indexterm:[SVG copy declaration,root]

=== Placement

The copies are added to the SVG image, as siblings of their originals.
That is, the copies are added just before their originals.
In the rectangles example above, this means that the `arect` copy is added just before the `rect` original, and the `grpb` copy is added just before the `grp` original.

The order of the `rect`, `rect2`, and `rect3` rectangles is important, in that it determines their _rendering order_.
Elements that are listed first, get _rendered_ or _painted_ first.
Subsequent elements are painted on top of previously painted elements.
Thus, the red `rect` rectangle is painted first, and is partially covered by the green `rect2` rectangle, which is painted second and is partially covered by the blue `rect3` rectangle, which is painted third.

By including copies near their originals (as siblings), the copies get a similar rendering order.

It is not allowed to copy the root element (the element with id `root` in the rectangles example above), as that would result in two root elements, which is not allowed by the SVG standard.

indexterm:[SVG copy declaration,uniqueness]

=== Uniqueness

All copied elements (the element that is copied, its children, the children of its children, etc) have their ids pre- and postfixed to create their new ids.
These ids must be unique in the SVG image.
That is, the new ids must not yet exist in the original SVG image, or have been used for previously copied elements.
The unique ids are required to ensure that we can still uniquely identify all elements by their ids, and we can thus use the ids to uniquely indicate to which elements other CIF/SVG declarations apply.

Consider once again the rectangles example above:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/svgcopy.svg[]
----

We add the following copy declaration:

[source, cif]
----
svgcopy id "rect" post "2";
----

This would result in the `rect` element being copied, and the copy being given a `rect2` id.
However, there is already an element with that id.
As such, the copy declaration is illegal.

At least a prefix or a postfix is required for every copy declaration, as otherwise the new ids would be identical to the original ids.

indexterm:[SVG copy declaration,overlap]

=== Overlap

Consider the following SVG file:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/overlap.svg[]
----

We use the following copy declarations:

[source, cif]
----
svgcopy id "g" post "a";
svgcopy id "r" post "b";
----

Both the `g` element and the `r` element are copied.
However, the `r` element is a part of the `g` element.
Therefore, the `r` element is copied twice, once for the copy of that element itself, and once for the copy of its parent (`g`).
This leads to the following SVG image:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/overlap_out1.svg[]
----

However, if we switch the order of the copies, we get:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/overlap_out2.svg[]
----

Copying an element twice by copying the element itself (e.g. `g`), but also copying an element that it contains (e.g. `r`) is not recommended.
As seen above, the outcome depends on the order, and can be very confusing.
CIF gives a warning in case such overlapping copies are used.
Generally, instead of copying the element twice, what is really wanted, is to copy the copied element.
This can be done as follows:

[source, cif]
----
svgcopy id "g" post "a";
svgcopy id "ra" post "b";
----

And this results in the following SVG file:

[source, svg]
----
include::{incdir-lang-ref-svg}/svgcopy/overlap_out3.svg[]
----

See the <<lang-tut-svg-chapter-example-buffers-products,buffers/products example>> for a more concrete example of the usefulness of copying copied elements.

Not that overlap is only detected for copying an element and an element that it contains.
Copying the same element multiple times is perfectly valid and useful, and does not result in warnings.

indexterm:[SVG copy declaration,application]
indexterm:[SVG copy declaration,order]

=== Application

Copy declarations are only applied once, before any <<lang-ref-svg-svgmove,CIF/SVG move declarations>> and <<lang-ref-svg-svgout,CIF/SVG output mappings>>.
