Using PDFNet to work with PDF Layers and optional content (OC) groups.

Q:

PDFTron PDFNet SDK looks very good, but I see no mention of two areas
of functionality that would be important to us:

- optional content (layers) and user properties (object data).

Would we have to use the SDF layer to implement these ourselves?
----
A:

Using PDFNet you can work (read/write/edit) with PDF layers and
optional content (OC) groups.

In the attachment you will find an example of a PDF document with
layers, generated using PDFNet. Layers are represented using Optional
Content (OC) grouping. OCGs are actually a generalizations of the
layer concept and can be used for many other purposes.

Using CosEdit (www.pdftron.com/cosedit), you will find 'OC' dictionary
entry in every image dictionary that associates the image/form with a
specific group/layer. Also the document catalog contains
'OCProperties' entry that lists content groups.

You can associate an Image/Form XObject with a given OCG (i.e. layer)
as follows:

// In C++
Obj* OC = doc.CreateIndirectDict();
OC->Put("Type", new Name("OCG"));
OC->Put("Name", new Name("Background"));
image.GetSDFObj()->Put("OC", OC);

// In C#
Obj OC = doc.CreateIndirectDict();
OC.Put("Type", pdftron.SDF.Obj.CreateName("OCG"));
OC.Put("Name", pdftron.SDF.Obj.CreateName("Background"));
image.GetSDFObj().Put("OC", OC);

The same idea works for form XObjects that can contain any PDF content
(text, vector art, and images).

OCProperties entry in the in document catalog can be created as
follows:

// C++
Obj* oc_props = new Dict();
doc.GetRoot()->Put("OCProperties", oc_props);
oc_props->Put(...)

// C#
Obj oc_props = Obj.CreateDict();
doc.GetRoot().Put("OCProperties", oc_props);
oc_props.Put(...)

It is usually recommended to group layers as separate form XObjects
(for efficiency, editing, etc). A side advantage of this approach is
that you don't need to tag elements with marked content. If for some
reason, you don't want to use form XObjects and would like to keep all
layers in a single content stream, you can inject markup tags using
writer.WriteString(...) method. For example,

writer.WriteString("/OC /oc1 BDC" )
writer.WriteElement(...);
...
writer.WriteString("EMC")

Properties entry in the resource dictionary can be created as
follows:

Obj* res = page.GetResources();
if (!res) {
  res = new Dict();
  page.GetSDFObj()->Put("Resources", res);
}

We are considering adding a very simple-to-use high-level API in the
near future, however the SDF/Cos API is more powerful and (in this
case) is as easy to use once you get a grip of it, which we can help
you with. Using SDK/Cos API you can also store custom properties and
streams in any PDF object (for example, see http://www.pdftron.com/net/samplecode/SDFTest.cs).