Sample code to use Apryse SDK for creating and manipulating PDF layers (also known as Optional Content Groups - OCGs). These samples demonstrate how to create and extract layers, as well as to selectively render them (show, hide) in conforming PDF readers or printers. Sample code provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.
Learn more about our Server SDK.
1//
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3//
4
5using System;
6using pdftron;
7using pdftron.Common;
8using pdftron.Filters;
9using pdftron.SDF;
10using pdftron.PDF;
11using pdftron.PDF.OCG;
12
13/// <summary>
14//-----------------------------------------------------------------------------------
15// This sample demonstrates how to create layers in PDF.
16// The sample also shows how to extract and render PDF layers in documents 
17// that contain optional content groups (OCGs)
18//
19// With the introduction of PDF version 1.5 came the concept of Layers. 
20// Layers, or as they are more formally known Optional Content Groups (OCGs),
21// refer to sections of content in a PDF document that can be selectively 
22// viewed or hidden by document authors or consumers. This capability is useful 
23// in CAD drawings, layered artwork, maps, multi-language documents etc.
24//
25// Notes: 
26// ---------------------------------------
27// - This sample is using CreateLayer() utility method to create new OCGs. 
28//   CreateLayer() is relatively basic, however it can be extended to set 
29//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
30//   a complete listing of possible entries in OC dictionary please refer to 
31//   section 4.10 'Optional Content' in the PDF Reference Manual.
32// - The sample is grouping all layer content into separate Form XObjects. 
33//   Although using PDFNet is is also possible to specify Optional Content in 
34//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
35//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
36//   to process.
37//-----------------------------------------------------------------------------------
38/// </summary>
39namespace PDFLayersTestCS
40{
41	class Class1 
42	{			
43		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
44		static Class1() {}
45		
46		// Relative path to the folder containing test files.
47		static string input_path =  "../../../../TestFiles/";
48		static string output_path = "../../../../TestFiles/Output/";
49
50		[STAThread]
51		static void Main(string[] args)
52		{
53			PDFNet.Initialize(PDFTronLicense.Key);
54
55			try
56			{
57				using (PDFDoc doc = new PDFDoc())
58				using (ElementBuilder builder = new ElementBuilder()) // ElementBuilder is used to build new Element objects
59				using (ElementWriter writer = new ElementWriter()) // ElementWriter is used to write Elements to the page
60				{
61					// Create three layers...
62					Group image_layer = CreateLayer(doc, "Image Layer");
63					Group text_layer = CreateLayer(doc, "Text Layer");
64					Group vector_layer = CreateLayer(doc, "Vector Layer");
65
66					// Start a new page ------------------------------------
67					Page page = doc.PageCreate();
68
69					writer.Begin(page);	// begin writing to this page
70
71					// Add new content to the page and associate it with one of the layers.
72					Element element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj()));
73					writer.WriteElement(element);
74
75					element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj()));
76					writer.WriteElement(element);
77
78					// Add the text layer to the page...
79					bool enableOCMD = false; // set to 'true' to enable 'ocmd' example.
80					if (enableOCMD)  
81					{
82						// A bit more advanced example of how to create an OCMD text layer that 
83						// is visible only if text, image and path layers are all 'ON'.
84						// An example of how to set 'Visibility Policy' in OCMD.
85						Obj ocgs = doc.CreateIndirectArray();
86						ocgs.PushBack(image_layer.GetSDFObj());
87						ocgs.PushBack(vector_layer.GetSDFObj());
88						ocgs.PushBack(text_layer.GetSDFObj());
89						OCMD text_ocmd = OCMD.Create(doc, ocgs, OCMD.VisibilityPolicyType.e_AllOn);
90						element = builder.CreateForm(CreateGroup3(doc, text_ocmd.GetSDFObj()));
91					}
92					else {
93						element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj()));
94					}
95					writer.WriteElement(element);
96
97					// Add some content to the page that does not belong to any layer...
98					// In this case this is a rectangle representing the page border.
99					element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight());
100					element.SetPathFill(false);
101					element.SetPathStroke(true);
102					element.GetGState().SetLineWidth(40);
103					writer.WriteElement(element);
104
105					writer.End();  // save changes to the current page
106					doc.PagePushBack(page);
107
108					// Set the default viewing preference to display 'Layer' tab.
109					PDFDocViewPrefs prefs = doc.GetViewPrefs();
110					prefs.SetPageMode(PDFDocViewPrefs.PageMode.e_UseOC);
111
112					doc.Save(output_path + "pdf_layers.pdf", SDFDoc.SaveOptions.e_linearized);
113					Console.WriteLine("Done.");
114				}
115			}
116			catch (PDFNetException e)
117			{
118				Console.WriteLine(e.Message);
119			}
120
121			// The following is a code snippet shows how to selectively render 
122			// and export PDF layers.
123			try  
124			{	 
125				using (PDFDoc doc = new PDFDoc(output_path + "pdf_layers.pdf"))
126				{
127					doc.InitSecurityHandler();
128
129					if (!doc.HasOC()) 
130					{
131						Console.WriteLine("The document does not contain 'Optional Content'");
132					}
133					else 
134					{
135						Config init_cfg = doc.GetOCGConfig();
136						Context ctx = new Context(init_cfg);
137
138						using (PDFDraw pdfdraw = new PDFDraw())
139						{
140							pdfdraw.SetImageSize(1000, 1000);
141							pdfdraw.SetOCGContext(ctx); // Render the page using the given OCG context.
142
143							Page page = doc.GetPage(1); // Get the first page in the document.
144							pdfdraw.Export(page, output_path + "pdf_layers_default.png");
145
146							// Disable drawing of content that is not optional (i.e. is not part of any layer).
147							ctx.SetNonOCDrawing(false);
148
149							// Now render each layer in the input document to a separate image.
150							Obj ocgs = doc.GetOCGs(); // Get the array of all OCGs in the document.
151							if (ocgs != null) 
152							{
153								int i, sz = ocgs.Size();
154								for (i=0; i<sz; ++i) 
155								{
156									Group ocg = new Group(ocgs.GetAt(i));
157									ctx.ResetStates(false);
158									ctx.SetState(ocg, true);
159									string fname = "pdf_layers_" + ocg.GetName() + ".png";
160									Console.WriteLine(fname);
161									pdfdraw.Export(page, output_path + fname);
162								}
163							}
164
165							// Now draw content that is not part of any layer...
166							ctx.SetNonOCDrawing(true);
167							ctx.SetOCDrawMode(Context.OCDrawMode.e_NoOC);
168							pdfdraw.Export(page, output_path + "pdf_layers_non_oc.png");
169
170							Console.WriteLine("Done.");
171						}
172					}
173				}
174			}
175			catch (PDFNetException e)
176			{
177				Console.WriteLine(e.Message);
178			}
179			PDFNet.Terminate();
180
181		}
182
183		// A utility function used to add new Content Groups (Layers) to the document.
184		static Group CreateLayer(PDFDoc doc, String layer_name)
185		{
186			Group grp = Group.Create(doc, layer_name);
187			Config cfg = doc.GetOCGConfig();
188			if (cfg == null) 
189			{
190				cfg = Config.Create(doc, true);
191				cfg.SetName("Default");
192			}
193
194			// Add the new OCG to the list of layers that should appear in PDF viewer GUI.
195			Obj layer_order_array = cfg.GetOrder();
196			if (layer_order_array == null) 
197			{
198				layer_order_array = doc.CreateIndirectArray();
199				cfg.SetOrder(layer_order_array);
200			}
201			layer_order_array.PushBack(grp.GetSDFObj());
202
203			return grp;
204		}
205
206		// Creates some content (3 images) and associate them with the image layer
207		static Obj CreateGroup1(PDFDoc doc, Obj layer)
208		{
209			using (ElementWriter writer = new ElementWriter())
210			using (ElementBuilder builder = new ElementBuilder())
211			{
212				writer.Begin(doc);
213
214				// Create an Image that can be reused in the document or on the same page.		
215				Image img = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"));
216
217				Element element = builder.CreateImage(img, new Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150));
218				writer.WritePlacedElement(element);
219
220				GState gstate = element.GetGState();	// use the same image (just change its matrix)
221				gstate.SetTransform(200, 0, 0, 300, 50, 450);
222				writer.WritePlacedElement(element);
223
224				// use the same image again (just change its matrix).
225				writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150));
226
227				Obj grp_obj = writer.End();	
228
229				// Indicate that this form (content group) belongs to the given layer (OCG).
230				grp_obj.PutName("Subtype","Form");
231				grp_obj.Put("OC", layer);	
232				grp_obj.PutRect("BBox", 0, 0, 1000, 1000);  // Set the clip box for the content.
233
234				// As an example of further configuration, set the image layer to
235				// be visible on screen, but not visible when printed...
236
237				// The AS entry is an auto state array consisting of one or more usage application 
238				// dictionaries that specify how conforming readers shall automatically set the 
239				// state of optional content groups based on external factors.
240				Obj cfg = doc.GetOCGConfig().GetSDFObj();
241				Obj auto_state = cfg.FindObj("AS");
242				if (auto_state == null) auto_state = cfg.PutArray("AS");
243				Obj print_state = auto_state.PushBackDict();
244				print_state.PutArray("Category").PushBackName("Print");
245				print_state.PutName("Event", "Print");
246				print_state.PutArray("OCGs").PushBack(layer);
247
248				Obj layer_usage = layer.PutDict("Usage");
249
250				Obj view_setting = layer_usage.PutDict("View");
251				view_setting.PutName("ViewState", "ON");
252
253				Obj print_setting = layer_usage.PutDict("Print");
254				print_setting.PutName("PrintState", "OFF");
255
256				return grp_obj;
257			}
258		}
259
260		// Creates some content (a path in the shape of a heart) and associate it with the vector layer
261		static Obj CreateGroup2(PDFDoc doc, Obj layer)
262		{
263			using (ElementWriter writer = new ElementWriter())
264			using (ElementBuilder builder = new ElementBuilder())
265			{
266				writer.Begin(doc);
267
268				// Create a path object in the shape of a heart.
269				builder.PathBegin();		// start constructing the path
270				builder.MoveTo(306, 396);
271				builder.CurveTo(681, 771, 399.75, 864.75, 306, 771);
272				builder.CurveTo(212.25, 864.75, -69, 771, 306, 396);
273				builder.ClosePath();
274				Element element = builder.PathEnd(); // the path geometry is now specified.
275
276				// Set the path FILL color space and color.
277				element.SetPathFill(true);
278				GState gstate = element.GetGState();
279				gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()); 
280				gstate.SetFillColor(new ColorPt(1, 0, 0, 0));  // cyan
281
282				// Set the path STROKE color space and color.
283				element.SetPathStroke(true); 
284				gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()); 
285				gstate.SetStrokeColor(new ColorPt(1, 0, 0));  // red
286				gstate.SetLineWidth(20);
287
288				gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300);
289
290				writer.WriteElement(element);
291
292				Obj grp_obj = writer.End();	
293
294
295				// Indicate that this form (content group) belongs to the given layer (OCG).
296				grp_obj.PutName("Subtype","Form");
297				grp_obj.Put("OC", layer);
298				grp_obj.PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
299
300				return grp_obj;
301			}
302		}
303
304		// Creates some text and associate it with the text layer
305		static Obj CreateGroup3(PDFDoc doc, Obj layer)
306		{
307			using (ElementWriter writer = new ElementWriter())
308			using (ElementBuilder builder = new ElementBuilder())
309			{
310				writer.Begin(doc);
311
312				// Begin writing a block of text
313				Element element = builder.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 120);
314				writer.WriteElement(element);
315
316				element = builder.CreateTextRun("A text layer!");
317
318				// Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
319				Matrix2D transform = Matrix2D.RotationMatrix(-45 *  (3.1415/ 180.0));
320				transform.Concat(1, 0, 0, 1, 180, 100);  
321				element.SetTextMatrix(transform);
322
323				writer.WriteElement(element);
324				writer.WriteElement(builder.CreateTextEnd());
325
326				Obj grp_obj = writer.End();	
327
328				// Indicate that this form (content group) belongs to the given layer (OCG).
329				grp_obj.PutName("Subtype","Form");
330				grp_obj.Put("OC", layer);
331				grp_obj.PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
332
333				return grp_obj;
334			}
335		}
336	}
337}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2021 by PDFTron Systems Inc. All Rights Reserved.
3// Consult LICENSE.txt regarding license information.
4//---------------------------------------------------------------------------------------
5
6package main
7import (
8    "fmt"
9    . "pdftron"
10)
11
12import  "pdftron/Samples/LicenseKey/GO"
13
14//-----------------------------------------------------------------------------------
15// This sample demonstrates how to create layers in PDF.
16// The sample also shows how to extract and render PDF layers in documents 
17// that contain optional content groups (OCGs)
18//
19// With the introduction of PDF version 1.5 came the concept of Layers. 
20// Layers, or as they are more formally known Optional Content Groups (OCGs),
21// refer to sections of content in a PDF document that can be selectively 
22// viewed or hidden by document authors or consumers. This capability is useful 
23// in CAD drawings, layered artwork, maps, multi-language documents etc.
24// 
25// Notes: 
26// ---------------------------------------
27// - This sample is using CreateLayer() utility method to create new OCGs. 
28//   CreateLayer() is relatively basic, however it can be extended to set 
29//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
30//   a complete listing of possible entries in OC dictionary please refer to 
31//   section 4.10 'Optional Content' in the PDF Reference Manual.
32// - The sample is grouping all layer content into separate Form XObjects. 
33//   Although using PDFNet is is also possible to specify Optional Content in 
34//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
35//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
36//   to process.
37//-----------------------------------------------------------------------------------
38
39// Relative path to the folder containing the test files.
40var inputPath = "../../TestFiles/"
41var outputPath = "../../TestFiles/Output/"
42
43// A utility function used to add new Content Groups (Layers) to the document.
44func CreateLayer(doc PDFDoc, layerName string) Group{
45    grp := GroupCreate(doc, layerName)
46    cfg := doc.GetOCGConfig()
47    if ! cfg.IsValid(){
48        cfg = ConfigCreate(doc, true)
49        cfg.SetName("Default")
50    }   
51    // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
52    layerOrderArray := cfg.GetOrder()
53    if layerOrderArray.GetMp_obj().Swigcptr() == 0{
54        layerOrderArray = doc.CreateIndirectArray()
55        cfg.SetOrder(layerOrderArray)
56    }
57    layerOrderArray.PushBack(grp.GetSDFObj())
58    return grp
59}
60// Creates some content (3 images) and associate them with the image layer
61func CreateGroup1(doc PDFDoc, layer Obj) Obj{
62    writer := NewElementWriter()
63    writer.Begin(doc.GetSDFDoc())
64    
65    // Create an Image that can be reused in the document or on the same page.
66    img := ImageCreate(doc.GetSDFDoc(), inputPath + "peppers.jpg")
67    builder := NewElementBuilder()
68    element := builder.CreateImage(img, NewMatrix2D(float64(img.GetImageWidth()/2), -145.0, 20.0, float64(img.GetImageHeight()/2), 200.0, 150.0))
69    writer.WritePlacedElement(element)
70    
71    gstate := element.GetGState()    // use the same image (just change its matrix)
72    gstate.SetTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0)
73    writer.WritePlacedElement(element)
74    
75    // use the same image again (just change its matrix).
76    writer.WritePlacedElement(builder.CreateImage(img, 300.0, 600.0, 200.0, -150.0))
77    
78    grpObj := writer.End()
79    
80    // Indicate that this form (content group) belongs to the given layer (OCG).
81    grpObj.PutName("Subtype","Form")
82    grpObj.Put("OC", layer)
83    grpObj.PutRect("BBox", 0.0, 0.0, 1000.0, 1000.0)   // Set the clip box for the content.
84    
85    return grpObj
86}
87// Creates some content (a path in the shape of a heart) and associate it with the vector layer
88func CreateGroup2(doc PDFDoc, layer Obj) Obj{
89    writer := NewElementWriter()
90    writer.Begin(doc.GetSDFDoc())
91    
92    // Create a path object in the shape of a heart
93    builder := NewElementBuilder()
94    builder.PathBegin()     // start constructing the path
95    builder.MoveTo(306.0, 396.0)
96    builder.CurveTo(681.0, 771.0, 399.75, 864.75, 306.0, 771.0)
97    builder.CurveTo(212.25, 864.75, -69, 771, 306.0, 396.0)
98    builder.ClosePath()
99    element := builder.PathEnd() // the path geometry is now specified.
100
101    // Set the path FILL color space and color.
102    element.SetPathFill(true)
103    gstate := element.GetGState()
104    gstate.SetFillColorSpace(ColorSpaceCreateDeviceCMYK())
105    gstate.SetFillColor(NewColorPt(1.0, 0.0, 0.0, 0.0))    // cyan
106    
107    // Set the path STROKE color space and color
108    element.SetPathStroke(true)
109    gstate.SetStrokeColorSpace(ColorSpaceCreateDeviceRGB())
110    gstate.SetStrokeColor(NewColorPt(1.0, 0.0, 0.0))     // red
111    gstate.SetLineWidth(20)
112    
113    gstate.SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0)
114    
115    writer.WriteElement(element)
116    
117    grpObj := writer.End()
118    
119    // Indicate that this form (content group) belongs to the given layer (OCG).
120    grpObj.PutName("Subtype","Form")
121    grpObj.Put("OC", layer)
122    grpObj.PutRect("BBox", 0.0, 0.0, 1000.0, 1000.0)       // Set the clip box for the content.
123    
124    return grpObj
125}
126// Creates some text and associate it with the text layer
127func CreateGroup3(doc PDFDoc, layer Obj) Obj{
128    writer := NewElementWriter()
129    writer.Begin(doc.GetSDFDoc())
130    
131    // Create a path object in the shape of a heart.
132    builder := NewElementBuilder()
133    
134    // Begin writing a block of text
135    element := builder.CreateTextBegin(FontCreate(doc.GetSDFDoc(), FontE_times_roman), 120.0)
136    writer.WriteElement(element)
137    
138    element = builder.CreateTextRun("A text layer!")
139    
140    // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
141    transform := Matrix2DRotationMatrix(-45 * (3.1415/ 180.0))
142    transform.Concat(1.0, 0.0, 0.0, 1.0, 180.0, 100.0)
143    element.SetTextMatrix(transform)
144    
145    writer.WriteElement(element)
146    writer.WriteElement(builder.CreateTextEnd())
147    
148    grpObj := writer.End()
149    
150    // Indicate that this form (content group) belongs to the given layer (OCG).
151    grpObj.PutName("Subtype","Form")
152    grpObj.Put("OC", layer)
153    grpObj.PutRect("BBox", 0.0, 0.0, 1000.0, 1000.0)   // Set the clip box for the content.
154    
155    return grpObj
156}
157
158func main(){
159    PDFNetInitialize(PDFTronLicense.Key)
160    
161    // Create three layers...
162    doc := NewPDFDoc()
163    imageLayer := CreateLayer(doc, "Image Layer")
164    textLayer := CreateLayer(doc, "Text Layer")
165    vectorLayer := CreateLayer(doc, "Vector Layer")
166    
167    // Start a new page ------------------------------------
168    page := doc.PageCreate()
169    
170    builder := NewElementBuilder()    // NewElementBuilder is used to build new Element objects
171    writer := NewElementWriter()      // NewElementWriter is used to write Elements to the page
172    writer.Begin(page)            // Begin writting to the page
173    
174    // Add new content to the page and associate it with one of the layers.
175    element := builder.CreateForm(CreateGroup1(doc, imageLayer.GetSDFObj()))
176    writer.WriteElement(element)
177    
178    element = builder.CreateForm(CreateGroup2(doc, vectorLayer.GetSDFObj()))
179    writer.WriteElement(element)
180    
181    // Add the text layer to the page...
182    if false{ // set to true to enable 'ocmd' example.
183        // A bit more advanced example of how to create an OCMD text layer that 
184        // is visible only if text, image and path layers are all 'ON'.
185        // An example of how to set 'Visibility Policy' in OCMD.
186        ocgs := doc.CreateIndirectArray()
187        ocgs.PushBack(imageLayer.GetSDFObj())
188        ocgs.PushBack(vectorLayer.GetSDFObj())
189        ocgs.PushBack(textLayer.GetSDFObj())
190        text_ocmd := OCMDCreate(doc, ocgs, OCMDE_AllOn)
191        element = builder.CreateForm(CreateGroup3(doc, text_ocmd.GetSDFObj()))
192    }else{
193        element = builder.CreateForm(CreateGroup3(doc, textLayer.GetSDFObj()))
194    }
195    writer.WriteElement(element)
196    
197    // Add some content to the page that does not belong to any layer...
198    // In this case this is a rectangle representing the page border.
199    element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight())
200    element.SetPathFill(false)
201    element.SetPathStroke(true)
202    element.GetGState().SetLineWidth(40)
203    writer.WriteElement(element)
204    
205    writer.End()    // save changes to the current page
206    doc.PagePushBack(page)
207    // Set the default viewing preference to display 'Layer' tab
208    prefs := doc.GetViewPrefs()
209    prefs.SetPageMode(PDFDocViewPrefsE_UseOC)
210    
211    doc.Save(outputPath + "pdf_layers.pdf", uint(SDFDocE_linearized))
212    doc.Close()
213    fmt.Println("Done.")
214    
215    // The following is a code snippet shows how to selectively render 
216    // and export PDF layers.
217    
218    doc = NewPDFDoc(outputPath + "pdf_layers.pdf")
219    doc.InitSecurityHandler()
220    
221    if ! doc.HasOC(){
222        fmt.Println("The document does not contain 'Optional Content'")
223    }else{
224        init_cfg := doc.GetOCGConfig()
225        ctx := NewContext(init_cfg)
226        
227        pdfdraw := NewPDFDraw()
228        pdfdraw.SetImageSize(1000, 1000)
229        pdfdraw.SetOCGContext(ctx)  // Render the page using the given OCG context.
230        
231        page = doc.GetPage(1)   // Get the first page in the document.
232        pdfdraw.Export(page, outputPath + "pdf_layers_default.png")
233        
234        // Disable drawing of content that is not optional (i.e. is not part of any layer).
235        ctx.SetNonOCDrawing(false)
236        
237        // Now render each layer in the input document to a separate image.
238        ocgs := doc.GetOCGs()    // Get the array of all OCGs in the document.
239        if ocgs != nil{
240            sz := ocgs.Size()
241            i := int64(0)
242            for i < sz{
243                ocg := NewGroup(ocgs.GetAt(i))
244                ctx.ResetStates(false)
245                ctx.SetState(ocg, true)
246                fname := "pdf_layers_" + ocg.GetName() + ".png"
247                fmt.Println(fname)
248                pdfdraw.Export(page, outputPath + fname)
249                i = i + 1
250            }
251        }
252        // Now draw content that is not part of any layer...
253        ctx.SetNonOCDrawing(true)
254        ctx.SetOCDrawMode(ContextE_NoOC)
255        pdfdraw.Export(page, outputPath + "pdf_layers_non_oc.png")
256        
257        doc.Close()
258        PDFNetTerminate()
259        fmt.Println("Done.") 
260    }
261}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6#include <SDF/Obj.h>
7#include <PDF/PDFNet.h>
8#include <PDF/PDFDoc.h>
9#include <PDF/PDFDraw.h>
10#include <PDF/OCG/OCMD.h>
11#include <PDF/ElementBuilder.h>
12#include <PDF/ElementWriter.h>
13#include <PDF/ElementReader.h>
14
15#include <iostream>
16#include "../../LicenseKey/CPP/LicenseKey.h"
17
18using namespace pdftron;
19using namespace Common;
20using namespace SDF;
21using namespace PDF;
22using namespace std;
23
24//-----------------------------------------------------------------------------------
25// This sample demonstrates how to create layers in PDF.
26// The sample also shows how to extract and render PDF layers in documents 
27// that contain optional content groups (OCGs)
28//
29// With the introduction of PDF version 1.5 came the concept of Layers. 
30// Layers, or as they are more formally known Optional Content Groups (OCGs),
31// refer to sections of content in a PDF document that can be selectively 
32// viewed or hidden by document authors or consumers. This capability is useful 
33// in CAD drawings, layered artwork, maps, multi-language documents etc.
34// 
35// Notes: 
36// ---------------------------------------
37// - This sample is using CreateLayer() utility method to create new OCGs. 
38//   CreateLayer() is relatively basic, however it can be extended to set 
39//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
40//   a complete listing of possible entries in OC dictionary please refer to 
41//   section 4.10 'Optional Content' in the PDF Reference Manual.
42// - The sample is grouping all layer content into separate Form XObjects. 
43//   Although using PDFNet is is also possible to specify Optional Content in 
44//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
45//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
46//   to process.
47//-----------------------------------------------------------------------------------
48
49Obj CreateGroup1(PDFDoc& doc, Obj layer);
50Obj CreateGroup2(PDFDoc& doc, Obj layer);
51Obj CreateGroup3(PDFDoc& doc, Obj layer);
52OCG::Group CreateLayer(PDFDoc& doc, const char* layer_name);
53
54// Relative path to the folder containing test files.
55static const string input_path =  "../../TestFiles/";
56static const string output_path = "../../TestFiles/Output/";
57
58int main(int argc, char *argv[])
59{
60	int ret = 0;
61	PDFNet::Initialize(LicenseKey);
62
63	try  
64	{	 
65		PDFDoc doc;
66
67		// Create three layers...
68		OCG::Group image_layer = CreateLayer(doc, "Image Layer");
69		OCG::Group text_layer = CreateLayer(doc, "Text Layer");
70		OCG::Group vector_layer = CreateLayer(doc, "Vector Layer");
71
72		// Start a new page ------------------------------------
73		Page page = doc.PageCreate();
74
75		ElementBuilder builder;	// ElementBuilder is used to build new Element objects
76		ElementWriter writer;	// ElementWriter is used to write Elements to the page	
77		writer.Begin(page);		// Begin writing to the page
78
79		// Add new content to the page and associate it with one of the layers.
80		Element element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj()));
81		writer.WriteElement(element);
82
83		element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj()));
84		writer.WriteElement(element);
85
86		// Add the text layer to the page...
87		if (false)  // set to true to enable 'ocmd' example.
88		{
89			// A bit more advanced example of how to create an OCMD text layer that 
90			// is visible only if text, image and path layers are all 'ON'.
91			// An example of how to set 'Visibility Policy' in OCMD.
92			Obj ocgs = doc.CreateIndirectArray();
93			ocgs.PushBack(image_layer.GetSDFObj());
94			ocgs.PushBack(vector_layer.GetSDFObj());
95			ocgs.PushBack(text_layer.GetSDFObj());
96			OCG::OCMD text_ocmd = OCG::OCMD::Create(doc, ocgs, OCG::OCMD::e_AllOn);
97			element = builder.CreateForm(CreateGroup3(doc, text_ocmd.GetSDFObj()));
98		}
99		else {
100			element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj()));
101		}
102		writer.WriteElement(element);
103
104		// Add some content to the page that does not belong to any layer...
105		// In this case this is a rectangle representing the page border.
106		element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight());
107		element.SetPathFill(false);
108		element.SetPathStroke(true);
109		element.GetGState().SetLineWidth(40);
110		writer.WriteElement(element);
111
112		writer.End();  // save changes to the current page
113		doc.PagePushBack(page);
114
115		// Set the default viewing preference to display 'Layer' tab.
116		PDFDocViewPrefs prefs = doc.GetViewPrefs();
117		prefs.SetPageMode(PDFDocViewPrefs::e_UseOC);
118
119		doc.Save((output_path + "pdf_layers.pdf").c_str(), SDFDoc::e_linearized, 0);
120		cout << "Done." << endl;
121	}
122	catch(Common::Exception& e)
123	{
124		cout << e << endl;
125		ret = 1;
126	}
127	catch(...)
128	{
129		cout << "Unknown Exception" << endl;
130		ret = 1;
131	}
132
133	// The following is a code snippet shows how to selectively render 
134	// and export PDF layers.
135	try  
136	{	 
137		PDFDoc doc((output_path + "pdf_layers.pdf").c_str());
138		doc.InitSecurityHandler();
139
140		if (!doc.HasOC()) {
141			cout << "The document does not contain 'Optional Content'" << endl;
142		}
143		else {
144			OCG::Config init_cfg = doc.GetOCGConfig();
145			OCG::Context ctx(init_cfg);
146
147			PDFDraw pdfdraw;
148			pdfdraw.SetImageSize(1000, 1000);
149			pdfdraw.SetOCGContext(&ctx); // Render the page using the given OCG context.
150
151			Page page = doc.GetPage(1); // Get the first page in the document.
152			pdfdraw.Export(page, (output_path + "pdf_layers_default.png").c_str());
153
154			// Disable drawing of content that is not optional (i.e. is not part of any layer).
155			ctx.SetNonOCDrawing(false);
156
157			// Now render each layer in the input document to a separate image.
158			Obj ocgs = doc.GetOCGs(); // Get the array of all OCGs in the document.
159			if (ocgs != 0) {
160				int i, sz = int(ocgs.Size());
161				for (i=0; i<sz; ++i) {
162					OCG::Group ocg(ocgs.GetAt(i));
163					ctx.ResetStates(false);
164					ctx.SetState(ocg, true);
165					std::string fname("pdf_layers_");
166					fname += ocg.GetName().ConvertToAscii();
167					fname += ".png";
168					cout << fname << endl;
169					pdfdraw.Export(page, (output_path + fname).c_str());
170				}
171			}
172
173			// Now draw content that is not part of any layer...
174			ctx.SetNonOCDrawing(true);
175			ctx.SetOCDrawMode(OCG::Context::e_NoOC);
176			pdfdraw.Export(page, (output_path + "pdf_layers_non_oc.png").c_str());
177		}
178
179		cout << "Done." << endl;
180	}
181	catch(Common::Exception& e)
182	{
183		cout << e << endl;
184		ret = 1;
185	}
186	catch(...)
187	{
188		cout << "Unknown Exception" << endl;
189		ret = 1;
190	}
191
192	PDFNet::Terminate();
193	return ret;
194}
195
196
197// A utility function used to add new Content Groups (Layers) to the document.
198OCG::Group CreateLayer(PDFDoc& doc, const char* layer_name)
199{
200	OCG::Group grp = OCG::Group::Create(doc, layer_name);
201	OCG::Config cfg = doc.GetOCGConfig();
202	if (!cfg.IsValid()) {
203		cfg = OCG::Config::Create(doc, true);
204		cfg.SetName("Default");
205	}
206
207	// Add the new OCG to the list of layers that should appear in PDF viewer GUI.
208	Obj layer_order_array = cfg.GetOrder();
209	if (!layer_order_array) {
210		layer_order_array = doc.CreateIndirectArray();
211		cfg.SetOrder(layer_order_array);
212	}
213	layer_order_array.PushBack(grp.GetSDFObj());
214
215	return grp;
216}
217
218// Creates some content (3 images) and associate them with the image layer
219Obj CreateGroup1(PDFDoc& doc, Obj layer) 
220{
221	ElementWriter writer;
222	writer.Begin(doc);
223
224	// Create an Image that can be reused in the document or on the same page.		
225	Image img = Image::Create(doc, (input_path + "peppers.jpg").c_str());
226
227	ElementBuilder builder;
228	Element element = builder.CreateImage(img, Common::Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150));
229	writer.WritePlacedElement(element);
230
231	GState gstate = element.GetGState();	// use the same image (just change its matrix)
232	gstate.SetTransform(200, 0, 0, 300, 50, 450);
233	writer.WritePlacedElement(element);
234
235	// use the same image again (just change its matrix).
236	writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150));
237
238	Obj grp_obj = writer.End();	
239
240	// Indicate that this form (content group) belongs to the given layer (OCG).
241	grp_obj.PutName("Subtype","Form");
242	grp_obj.Put("OC", layer);	
243	grp_obj.PutRect("BBox", 0, 0, 1000, 1000);  // Set the clip box for the content.
244
245	return grp_obj;
246}
247
248// Creates some content (a path in the shape of a heart) and associate it with the vector layer
249Obj CreateGroup2(PDFDoc& doc, Obj layer) 
250{
251	ElementWriter writer;
252	writer.Begin(doc);
253
254	// Create a path object in the shape of a heart.
255	ElementBuilder builder;
256	builder.PathBegin();		// start constructing the path
257	builder.MoveTo(306, 396);
258	builder.CurveTo(681, 771, 399.75, 864.75, 306, 771);
259	builder.CurveTo(212.25, 864.75, -69, 771, 306, 396);
260	builder.ClosePath();
261	Element element = builder.PathEnd(); // the path geometry is now specified.
262
263	// Set the path FILL color space and color.
264	element.SetPathFill(true);
265	GState gstate = element.GetGState();
266	gstate.SetFillColorSpace(ColorSpace::CreateDeviceCMYK()); 
267	gstate.SetFillColor(ColorPt(1, 0, 0, 0));  // cyan
268
269	// Set the path STROKE color space and color.
270	element.SetPathStroke(true); 
271	gstate.SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
272	gstate.SetStrokeColor(ColorPt(1, 0, 0));  // red
273	gstate.SetLineWidth(20);
274
275	gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300);
276
277	writer.WriteElement(element);
278
279	Obj grp_obj = writer.End();	
280
281	// Indicate that this form (content group) belongs to the given layer (OCG).
282	grp_obj.PutName("Subtype","Form");
283	grp_obj.Put("OC", layer);
284	grp_obj.PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
285
286	return grp_obj;
287}
288
289// Creates some text and associate it with the text layer
290Obj CreateGroup3(PDFDoc& doc, Obj layer) 
291{
292	ElementWriter writer;
293	writer.Begin(doc);
294
295	// Create a path object in the shape of a heart.
296	ElementBuilder builder;
297
298	// Begin writing a block of text
299	Element element = builder.CreateTextBegin(Font::Create(doc, Font::e_times_roman), 120);
300	writer.WriteElement(element);
301
302	element = builder.CreateTextRun("A text layer!");
303
304	// Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
305	Matrix2D transform = Matrix2D::RotationMatrix(-45 *  (3.1415/ 180.0));
306	transform *= Matrix2D(1, 0, 0, 1, 180, 100);  
307	element.SetTextMatrix(transform);
308
309	writer.WriteElement(element);
310	writer.WriteElement(builder.CreateTextEnd());
311
312	Obj grp_obj = writer.End();	
313
314	// Indicate that this form (content group) belongs to the given layer (OCG).
315	grp_obj.PutName("Subtype","Form");
316	grp_obj.Put("OC", layer);
317	grp_obj.PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
318
319	return grp_obj;
320}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6import com.pdftron.common.Matrix2D;
7import com.pdftron.common.PDFNetException;
8import com.pdftron.pdf.*;
9import com.pdftron.pdf.ocg.*;
10import com.pdftron.sdf.*;
11
12
13//-----------------------------------------------------------------------------------
14// This sample demonstrates how to create layers in PDF.
15// The sample also shows how to extract and render PDF layers in documents 
16// that contain optional content groups (OCGs)
17//
18// With the introduction of PDF version 1.5 came the concept of Layers. 
19// Layers, or as they are more formally known Optional Content Groups (OCGs),
20// refer to sections of content in a PDF document that can be selectively 
21// viewed or hidden by document authors or consumers. This capability is useful 
22// in CAD drawings, layered artwork, maps, multi-language documents etc.
23//
24// Couple of notes regarding this sample: 
25// ---------------------------------------
26// - This sample is using CreateLayer() utility method to create new OCGs. 
27//   CreateLayer() is relatively basic, however it can be extended to set 
28//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
29//   a complete listing of possible entries in OC dictionary please refer to 
30//   section 4.10 'Optional Content' in the PDF Reference Manual.
31// - The sample is grouping all layer content into separate Form XObjects. 
32//   Although using PDFNet is is also possible to specify Optional Content in 
33//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
34//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
35//   to process.
36//-----------------------------------------------------------------------------------
37public class PDFLayersTest {
38    // Relative path to the folder containing test files.
39    static String input_path = "../../TestFiles/";
40    static String output_path = "../../TestFiles/Output/";
41
42    public static void main(String[] args) {
43        PDFNet.initialize(PDFTronLicense.Key());
44
45        try (PDFDoc doc = new PDFDoc()) {
46            // Create three layers...
47            Group image_layer = createLayer(doc, "Image Layer");
48            Group text_layer = createLayer(doc, "Text Layer");
49            Group vector_layer = createLayer(doc, "Vector Layer");
50
51            // Start a new page ------------------------------------
52            Page page = doc.pageCreate();
53
54            ElementBuilder builder = new ElementBuilder(); // ElementBuilder is used to build new Element objects
55            ElementWriter writer = new ElementWriter(); // ElementWriter is used to write Elements to the page
56            writer.begin(page);        // Begin writing to the page
57
58            // Add new content to the page and associate it with one of the layers.
59            Element element = builder.createForm(createGroup1(doc, image_layer.getSDFObj()));
60            writer.writeElement(element);
61
62            element = builder.createForm(createGroup2(doc, vector_layer.getSDFObj()));
63            writer.writeElement(element);
64
65            // Add the text layer to the page...
66            if (false)  // set to true to enable 'ocmd' example.
67            {
68                // A bit more advanced example of how to create an OCMD text layer that
69                // is visible only if text, image and path layers are all 'ON'.
70                // An example of how to set 'Visibility Policy' in OCMD.
71                Obj ocgs = doc.createIndirectArray();
72                ocgs.pushBack(image_layer.getSDFObj());
73                ocgs.pushBack(vector_layer.getSDFObj());
74                ocgs.pushBack(text_layer.getSDFObj());
75                OCMD text_ocmd = OCMD.create(doc, ocgs, OCMD.e_AllOn);
76                element = builder.createForm(createGroup3(doc, text_ocmd.getSDFObj()));
77            } else {
78                element = builder.createForm(createGroup3(doc, text_layer.getSDFObj()));
79            }
80            writer.writeElement(element);
81
82
83            // Add some content to the page that does not belong to any layer...
84            // In this case this is a rectangle representing the page border.
85            element = builder.createRect(0, 0, page.getPageWidth(), page.getPageHeight());
86            element.setPathFill(false);
87            element.setPathStroke(true);
88            element.getGState().setLineWidth(40);
89            writer.writeElement(element);
90
91            writer.end();  // save changes to the current page
92            doc.pagePushBack(page);
93
94            // Set the default viewing preference to display 'Layer' tab.
95            PDFDocViewPrefs prefs = doc.getViewPrefs();
96            prefs.setPageMode(PDFDocViewPrefs.e_UseOC);
97
98            doc.save(output_path + "pdf_layers.pdf", SDFDoc.SaveMode.LINEARIZED, null);
99            System.out.println("Done.");
100        } catch (Exception e) {
101            e.printStackTrace();
102        }
103
104        // The following is a code snippet shows how to selectively render
105        // and export PDF layers.
106        try (PDFDoc doc = new PDFDoc(output_path + "pdf_layers.pdf")) {
107            doc.initSecurityHandler();
108
109            if (doc.hasOC() == false) {
110                System.out.println("The document does not contain 'Optional Content'");
111            } else {
112                Config init_cfg = doc.getOCGConfig();
113                Context ctx = new Context(init_cfg);
114
115                PDFDraw pdfdraw = new PDFDraw();
116                pdfdraw.setImageSize(1000, 1000);
117                pdfdraw.setOCGContext(ctx); // Render the page using the given OCG context.
118
119                Page page = doc.getPage(1); // Get the first page in the document.
120                pdfdraw.export(page, output_path + "pdf_layers_default.png");
121                // output "pdf_layers_default.png"
122
123                // Disable drawing of content that is not optional (i.e. is not part of any layer).
124                ctx.setNonOCDrawing(false);
125
126                // Now render each layer in the input document to a separate image.
127                Obj ocgs = doc.getOCGs(); // Get the array of all OCGs in the document.
128                if (ocgs != null) {
129                    int i, sz = (int) ocgs.size();
130                    for (i = 0; i < sz; ++i) {
131                        Group ocg = new Group(ocgs.getAt(i));
132                        ctx.resetStates(false);
133                        ctx.setState(ocg, true);
134                        String fname =  "pdf_layers_" + ocg.getName() + ".png";
135                        System.out.println(fname);
136                        pdfdraw.export(page, output_path + fname);
137                        // output "pdf_layers_" + ocg.getName() + ".png"
138                    }
139                }
140
141                // Now draw content that is not part of any layer...
142                ctx.setNonOCDrawing(true);
143                ctx.setOCDrawMode(Context.e_NoOC);
144                pdfdraw.export(page, output_path + "pdf_layers_non_oc.png");
145                // output "pdf_layers_non_oc.png"
146            }
147
148            System.out.println("Done.");
149        } catch (Exception e) {
150            e.printStackTrace();
151        }
152
153        PDFNet.terminate();
154    }
155
156    // A utility function used to add new Content Groups (Layers) to the document.
157    static Group createLayer(PDFDoc doc, String layer_name) throws PDFNetException {
158        Group grp = Group.create(doc, layer_name);
159        Config cfg = doc.getOCGConfig();
160        if (cfg == null) {
161            cfg = Config.create(doc, true);
162            cfg.setName("Default");
163        }
164
165        // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
166        Obj layer_order_array = cfg.getOrder();
167        if (layer_order_array == null) {
168            layer_order_array = doc.createIndirectArray();
169            cfg.setOrder(layer_order_array);
170        }
171        layer_order_array.pushBack(grp.getSDFObj());
172
173        return grp;
174    }
175
176    // Creates some content (3 images) and associate them with the image layer
177    static Obj createGroup1(PDFDoc doc, Obj layer) throws PDFNetException {
178        ElementWriter writer = new ElementWriter();
179        writer.begin(doc);
180
181        // Create an Image that can be reused in the document or on the same page.
182        Image img = Image.create(doc.getSDFDoc(), (input_path + "peppers.jpg"));
183
184        ElementBuilder builder = new ElementBuilder();
185        Element element = builder.createImage(img, new Matrix2D(img.getImageWidth() / 2, -145, 20, img.getImageHeight() / 2, 200, 150));
186        writer.writePlacedElement(element);
187
188        GState gstate = element.getGState();    // use the same image (just change its matrix)
189        gstate.setTransform(200, 0, 0, 300, 50, 450);
190        writer.writePlacedElement(element);
191
192        // use the same image again (just change its matrix).
193        writer.writePlacedElement(builder.createImage(img, 300, 600, 200, -150));
194
195        Obj grp_obj = writer.end();
196
197        // Indicate that this form (content group) belongs to the given layer (OCG).
198        grp_obj.putName("Subtype", "Form");
199        grp_obj.put("OC", layer);
200        grp_obj.putRect("BBox", 0, 0, 1000, 1000);  // Set the clip box for the content.
201
202        return grp_obj;
203    }
204
205    // Creates some content (a path in the shape of a heart) and associate it with the vector layer
206    static Obj createGroup2(PDFDoc doc, Obj layer) throws PDFNetException {
207        ElementWriter writer = new ElementWriter();
208        writer.begin(doc);
209
210        // Create a path object in the shape of a heart.
211        ElementBuilder builder = new ElementBuilder();
212        builder.pathBegin();        // start constructing the path
213        builder.moveTo(306, 396);
214        builder.curveTo(681, 771, 399.75, 864.75, 306, 771);
215        builder.curveTo(212.25, 864.75, -69, 771, 306, 396);
216        builder.closePath();
217        Element element = builder.pathEnd(); // the path geometry is now specified.
218
219        // Set the path FILL color space and color.
220        element.setPathFill(true);
221        GState gstate = element.getGState();
222        gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
223        gstate.setFillColor(new ColorPt(1, 0, 0, 0));  // cyan
224
225        // Set the path STROKE color space and color.
226        element.setPathStroke(true);
227        gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
228        gstate.setStrokeColor(new ColorPt(1, 0, 0));  // red
229        gstate.setLineWidth(20);
230
231        gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
232
233        writer.writeElement(element);
234
235        Obj grp_obj = writer.end();
236
237        // Indicate that this form (content group) belongs to the given layer (OCG).
238        grp_obj.putName("Subtype", "Form");
239        grp_obj.put("OC", layer);
240        grp_obj.putRect("BBox", 0, 0, 1000, 1000);    // Set the clip box for the content.
241
242        return grp_obj;
243    }
244
245    // Creates some text and associate it with the text layer
246    static Obj createGroup3(PDFDoc doc, Obj layer) throws PDFNetException {
247        ElementWriter writer = new ElementWriter();
248        writer.begin(doc);
249
250        // Create a path object in the shape of a heart.
251        ElementBuilder builder = new ElementBuilder();
252
253        // Begin writing a block of text
254        Element element = builder.createTextBegin(Font.create(doc, Font.e_times_roman), 120);
255        writer.writeElement(element);
256
257        element = builder.createTextRun("A text layer!");
258
259        // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
260        Matrix2D transform = Matrix2D.rotationMatrix(-45 * (3.1415 / 180.0));
261        transform.concat(1, 0, 0, 1, 180, 100);
262        element.setTextMatrix(transform);
263
264        writer.writeElement(element);
265        writer.writeElement(builder.createTextEnd());
266
267        Obj grp_obj = writer.end();
268
269        // Indicate that this form (content group) belongs to the given layer (OCG).
270        grp_obj.putName("Subtype", "Form");
271        grp_obj.put("OC", layer);
272        grp_obj.putRect("BBox", 0, 0, 1000, 1000);    // Set the clip box for the content.
273
274        return grp_obj;
275    }
276}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6//-----------------------------------------------------------------------------------
7// This sample demonstrates how to create layers in PDF.
8// The sample also shows how to extract and render PDF layers in documents 
9// that contain optional content groups (OCGs)
10//
11// With the introduction of PDF version 1.5 came the concept of Layers. 
12// Layers, or as they are more formally known Optional Content Groups (OCGs),
13// refer to sections of content in a PDF document that can be selectively 
14// viewed or hidden by document authors or consumers. This capability is useful 
15// in CAD drawings, layered artwork, maps, multi-language documents etc.
16// 
17// Notes: 
18// ---------------------------------------
19// - This sample is using CreateLayer() utility method to create new OCGs. 
20//   CreateLayer() is relatively basic, however it can be extended to set 
21//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
22//   a complete listing of possible entries in OC dictionary please refer to 
23//   section 4.10 'Optional Content' in the PDF Reference Manual.
24// - The sample is grouping all layer content into separate Form XObjects. 
25//   Although using PDFNet is is also possible to specify Optional Content in 
26//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
27//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
28//   to process.
29//-----------------------------------------------------------------------------------
30
31const { PDFNet } = require('@pdftron/pdfnet-node');
32const PDFTronLicense = require('../LicenseKey/LicenseKey');
33
34((exports) => {
35
36  exports.runPDFLayersTest = () => {
37    const inputPath =  '../TestFiles/';
38    const outputPath = inputPath + 'Output/';
39
40    // A utility function used to add new Content Groups (Layers) to the document.
41    const CreateLayer = async(doc, layerName) => {
42      await PDFNet.startDeallocateStack();
43      const grp = await PDFNet.OCG.create(doc, layerName);
44      let cfg = await doc.getOCGConfig();
45      if (cfg == null) {
46        cfg = await PDFNet.OCGConfig.create(doc, true);
47        cfg.setName('Default');
48      }
49
50      // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
51      let layerOrderArray = await cfg.getOrder();
52      if (layerOrderArray == null) {
53        layerOrderArray = await doc.createIndirectArray();
54        cfg.setOrder(layerOrderArray);
55      }
56      const grpSDFObj = await grp.getSDFObj();
57      layerOrderArray.pushBack(grpSDFObj);
58
59      await PDFNet.endDeallocateStack();
60      return grp;
61    };
62
63    // Creates some content (3 images) and associate them with the image layer
64    const CreateGroup1 = async(doc, layer) => {
65      await PDFNet.startDeallocateStack();
66      const writer = await PDFNet.ElementWriter.create();
67      writer.begin(doc);
68
69      // Create an Image that can be reused in the document or on the same page.
70      const img = await PDFNet.Image.createFromFile(doc, inputPath + 'peppers.jpg');
71
72      const builder = await PDFNet.ElementBuilder.create();
73      const imgWidth = await img.getImageWidth();
74      const imgHeight = await img.getImageHeight();
75      const imgMatrix = new PDFNet.Matrix2D(imgWidth / 2, -145, 20, imgHeight / 2, 200, 150);
76      const element = await builder.createImageFromMatrix(img, imgMatrix);
77      writer.writePlacedElement(element);
78
79      const gstate = await element.getGState(); // use the same image (just change its matrix)
80      gstate.setTransform(200, 0, 0, 300, 50, 450);
81      writer.writePlacedElement(element);
82
83      // use the same image again (just change its matrix).
84      writer.writePlacedElement(await builder.createImageScaled(img, 300, 600, 200, -150));
85
86      const grpObj = await writer.end();
87
88      // Indicate that this form (content group) belongs to the given layer (OCG).
89      grpObj.putName('Subtype', 'Form');
90      grpObj.put('OC', layer);
91      grpObj.putRect('BBox', 0, 0, 1000, 1000); // Set the clip box for the content.
92      await PDFNet.endDeallocateStack();
93
94      return grpObj;
95    };
96
97    const CreateGroup2 = async(doc, layer) => {
98      await PDFNet.startDeallocateStack();
99      const writer = await PDFNet.ElementWriter.create();
100      writer.begin(doc);
101
102      // Create a path object in the shape of a heart.
103      const builder = await PDFNet.ElementBuilder.create();
104      builder.pathBegin(); // start constructing the path
105      builder.moveTo(306, 396);
106      builder.curveTo(681, 771, 399.75, 864.75, 306, 771);
107      builder.curveTo(212.25, 864.75, -69, 771, 306, 396);
108      builder.closePath();
109      const element = await builder.pathEnd(); // the path geometry is now specified.
110
111      // Set the path FILL color space and color.
112      element.setPathFill(true);
113      const gstate = await element.getGState();
114      const CMYKSpace = await PDFNet.ColorSpace.createDeviceCMYK();
115      gstate.setFillColorSpace(CMYKSpace);
116      const cyanColorPt = await PDFNet.ColorPt.init(1, 0, 0, 0); // CMYK
117      gstate.setFillColorWithColorPt(cyanColorPt); // cyan
118
119      // Set the path STROKE color space and color.
120      element.setPathStroke(true);
121      const RGBSpace = await PDFNet.ColorSpace.createDeviceRGB();
122      gstate.setStrokeColorSpace(RGBSpace);
123      const redColorPt = await PDFNet.ColorPt.init(1, 0, 0); // RGB
124      gstate.setStrokeColorWithColorPt(redColorPt); // red
125      gstate.setLineWidth(20);
126
127      gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
128
129      writer.writeElement(element);
130
131      const grpObj = await writer.end();
132
133      // Indicate that this form (content group) belongs to the given layer (OCG).
134      grpObj.putName('Subtype', 'Form');
135      grpObj.put('OC', layer);
136      grpObj.putRect('BBox', 0, 0, 1000, 1000); // Set the clip box for the content.
137
138      await PDFNet.endDeallocateStack();
139      return grpObj;
140    };
141
142    const CreateGroup3 = async(doc, layer) => {
143      await PDFNet.startDeallocateStack();
144      const writer = await PDFNet.ElementWriter.create();
145      writer.begin(doc);
146
147      const builder = await PDFNet.ElementBuilder.create();
148
149      // Begin writing a block of text
150      const textFont = await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman);
151      let element = await builder.createTextBeginWithFont(textFont, 120);
152      writer.writeElement(element);
153
154      element = await builder.createNewTextRun('A text layer!');
155
156      // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
157      const transform = await PDFNet.Matrix2D.createRotationMatrix(-45 * (3.1415 / 180.0));
158      await transform.concat(1, 0, 0, 1, 180, 100);
159      await element.setTextMatrix(transform);
160
161      await writer.writeElement(element);
162      await writer.writeElement(await builder.createTextEnd());
163
164      const grpObj = await writer.end();
165
166      // Indicate that this form (content group) belongs to the given layer (OCG).
167      grpObj.putName('Subtype', 'Form');
168      grpObj.put('OC', layer);
169      grpObj.putRect('BBox', 0, 0, 1000, 1000); // Set the clip box for the content.
170      await PDFNet.endDeallocateStack();
171      return grpObj;
172    };
173
174
175    const main = async() => {
176      try {
177        const doc = await PDFNet.PDFDoc.create();
178        doc.initSecurityHandler();
179
180        const imageLayer = await CreateLayer(doc, 'Image Layer');
181        const textLayer = await CreateLayer(doc, 'Text Layer');
182        const vectorLayer = await CreateLayer(doc, 'Vector Layer');
183
184        // Start a new page ------------------------------------
185        const page = await doc.pageCreate();
186
187        const builder = await PDFNet.ElementBuilder.create();	 // ElementBuilder is used to build new Element objects
188        const writer = await PDFNet.ElementWriter.create();  // ElementWriter is used to write Elements to the page
189        writer.beginOnPage(page);  // Begin writing to the page
190
191        const groupObj = await CreateGroup1(doc, (await imageLayer.getSDFObj()));
192        let element = await builder.createFormFromStream(groupObj);
193        writer.writeElement(element);
194
195        const groupObj2 = await CreateGroup2(doc, (await vectorLayer.getSDFObj()));
196        element = await builder.createFormFromStream(groupObj2);
197        writer.writeElement(element);
198
199        // eslint-disable-next-line no-constant-condition
200        if (false) {
201          // A bit more advanced example of how to create an OCMD text layer that
202          // is visible only if text, image and path layers are all 'ON'.
203          // An example of how to set 'Visibility Policy' in OCMD.
204          const ocgs = doc.createIndirectArray();
205          ocgs.pushBack(await imageLayer.getSDFObj());
206          ocgs.pushBack(await vectorLayer.getSDFObj());
207          ocgs.PushBack(await textLayer.getSDFObj());
208          const textOcmd = await PDFNet.OCMD.create(doc, ocgs, PDFNet.OCMD.VisibilityPolicyType.e_AllOn);
209          element = await builder.createFormFromStream(await CreateGroup3(doc, (await textOcmd.getSDFObj())));
210        } else {
211          // let SDFObj = await textLayer.getSDFObj();
212          element = await builder.createFormFromStream(await CreateGroup3(doc, (await textLayer.getSDFObj())));
213        }
214        writer.writeElement(element);
215
216        // Add some content to the page that does not belong to any layer...
217        // In this case this is a rectangle representing the page border.
218        element = await builder.createRect(0, 0, (await page.getPageWidth()), (await page.getPageHeight()));
219        element.setPathFill(false);
220        element.setPathStroke(true);
221        const elementGState = await element.getGState();
222        elementGState.setLineWidth(40);
223        writer.writeElement(element);
224
225        writer.end(); // save changes to the current page
226        doc.pagePushBack(page);
227
228        // Set the default viewing preference to display 'Layer' tab.
229        const prefs = await doc.getViewPrefs();
230        prefs.setPageMode(PDFNet.PDFDocViewPrefs.PageMode.e_UseOC);
231
232        await doc.save(outputPath + 'pdf_layers.pdf', PDFNet.SDFDoc.SaveOptions.e_linearized);
233        console.log('Done.');
234      } catch (err) {
235        // console.log(err);
236        console.log(err.stack);
237      }
238
239      // The following is a code snippet shows how to selectively render 
240      // and export PDF layers.
241      try {
242        const doc = await PDFNet.PDFDoc.createFromFilePath(outputPath + 'pdf_layers.pdf');
243        doc.initSecurityHandler();
244
245        if (!(await doc.hasOC())) {
246          console.log("The document does not contain 'Optional Content'");
247        } else {
248          const initCfg = await doc.getOCGConfig();
249          const ctx = await PDFNet.OCGContext.createFromConfig(initCfg);
250
251          const pdfdraw = await PDFNet.PDFDraw.create();
252          pdfdraw.setImageSize(1000, 1000);
253          pdfdraw.setOCGContext(ctx);
254
255          const page = await doc.getPage(1);
256
257          await pdfdraw.export(page, outputPath + 'pdf_layers_default.png');
258
259          // Disable drawing of content that is not optional (i.e. is not part of any layer).
260          ctx.setNonOCDrawing(false);
261
262          // Now render each layer in the input document to a separate image.
263          const ocgs = await doc.getOCGs();
264          if (ocgs !== null) {
265            let i;
266            const sz = await ocgs.size();
267            for (i = 0; i < sz; ++i) {
268              const ocg = await PDFNet.OCG.createFromObj(await ocgs.getAt(i));
269              ctx.resetStates(false);
270              await ctx.setState(ocg, true);
271              let fname = 'pdf_layers_';
272              fname += await ocg.getName();
273              fname += '.png';
274              console.log(fname);
275              await pdfdraw.export(page, outputPath + fname);
276            }
277          }
278
279          // Now draw content that is not part of any layer...
280          ctx.setNonOCDrawing(true);
281          await ctx.setOCDrawMode(PDFNet.OCGContext.OCDrawMode.e_NoOC);
282          await pdfdraw.export(page, outputPath + 'pdf_layers_non_oc.png');
283        }
284
285        console.log('Done.');
286      } catch (err) {
287        console.log(err.stack);
288      }
289    };
290    PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error){console.log('Error: ' + JSON.stringify(error));}).then(function(){return PDFNet.shutdown();});
291  };
292  exports.runPDFLayersTest();
293})(exports);
294// eslint-disable-next-line spaced-comment
295//# sourceURL=PDFLayersTest.js
1#---------------------------------------------------------------------------------------
2# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
3# Consult LICENSE.txt regarding license information.
4#---------------------------------------------------------------------------------------
5
6require '../../../PDFNetC/Lib/PDFNetRuby'
7include PDFNetRuby
8require '../../LicenseKey/RUBY/LicenseKey'
9
10$stdout.sync = true
11
12#-----------------------------------------------------------------------------------
13# This sample demonstrates how to create layers in PDF.
14# The sample also shows how to extract and render PDF layers in documents 
15# that contain optional content groups (OCGs)
16#
17# With the introduction of PDF version 1.5 came the concept of Layers. 
18# Layers, or as they are more formally known Optional Content Groups (OCGs),
19# refer to sections of content in a PDF document that can be selectively 
20# viewed or hidden by document authors or consumers. This capability is useful 
21# in CAD drawings, layered artwork, maps, multi-language documents etc.
22# 
23# Notes: 
24# ---------------------------------------
25# - This sample is using CreateLayer utility method to create new OCGs. 
26#   CreateLayer is relatively basic, however it can be extended to set 
27#   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
28#   a complete listing of possible entries in OC dictionary please refer to 
29#   section 4.10 'Optional Content' in the PDF Reference Manual.
30# - The sample is grouping all layer content into separate Form XObjects. 
31#   Although using PDFNet is is also possible to specify Optional Content in 
32#   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
33#   XObjects results in PDFs that are cleaner, less-error prone, and faster 
34#   to process.
35#-----------------------------------------------------------------------------------
36
37# Relative path to the folder containing the test files.
38$input_path = "../../TestFiles/"
39$output_path = "../../TestFiles/Output/"
40
41# A utility function used to add new Content Groups (Layers) to the document.
42def CreateLayer(doc, layer_name)
43	grp = Group.Create(doc, layer_name)
44	cfg = doc.GetOCGConfig
45	if !cfg.IsValid
46		cfg = PDFNetRuby::Config.Create(doc, true)
47		cfg.SetName("Default")
48	end
49		
50	# Add the new OCG to the list of layers that should appear in PDF viewer GUI.
51	layer_order_array = cfg.GetOrder
52	if layer_order_array.nil?
53		layer_order_array = doc.CreateIndirectArray
54		cfg.SetOrder(layer_order_array)
55	end
56	layer_order_array.PushBack(grp.GetSDFObj)
57	return grp
58end
59
60# Creates some content (3 images) and associate them with the image layer
61def CreateGroup1(doc, layer)
62	writer = ElementWriter.new
63	writer.Begin(doc.GetSDFDoc)
64	
65	# Create an Image that can be reused in the document or on the same page.
66	img = Image.Create(doc.GetSDFDoc, $input_path + "peppers.jpg")
67	builder = ElementBuilder.new
68	element = builder.CreateImage(img, Matrix2D.new(img.GetImageWidth/2, -145, 20, img.GetImageHeight/2, 200, 150))
69	writer.WritePlacedElement(element)
70	
71	gstate = element.GetGState	# use the same image (just change its matrix)
72	gstate.SetTransform(200, 0, 0, 300, 50, 450)
73	writer.WritePlacedElement(element)
74	
75	# use the same image again (just change its matrix).
76	writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150))
77	
78	grp_obj = writer.End
79	
80	# Indicate that this form (content group) belongs to the given layer (OCG).
81	grp_obj.PutName("Subtype","Form")
82	grp_obj.Put("OC", layer)
83	grp_obj.PutRect("BBox", 0, 0, 1000, 1000)   # Set the clip box for the content.
84	
85	return grp_obj
86end
87
88# Creates some content (a path in the shape of a heart) and associate it with the vector layer
89def CreateGroup2(doc, layer)
90	writer = ElementWriter.new
91	writer.Begin(doc.GetSDFDoc)
92	
93	# Create a path object in the shape of a heart
94	builder = ElementBuilder.new
95	builder.PathBegin	 # start constructing the path
96	builder.MoveTo(306, 396)
97	builder.CurveTo(681, 771, 399.75, 864.75, 306, 771)
98	builder.CurveTo(212.25, 864.75, -69, 771, 306, 396)
99	builder.ClosePath
100	element = builder.PathEnd # the path geometry is now specified.
101
102	# Set the path FILL color space and color.
103	element.SetPathFill(true)
104	gstate = element.GetGState
105	gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK)
106	gstate.SetFillColor(ColorPt.new(1, 0, 0, 0))	# cyan
107	
108	# Set the path STROKE color space and color
109	element.SetPathStroke(true)
110	gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB)
111	gstate.SetStrokeColor(ColorPt.new(1, 0, 0))	 # red
112	gstate.SetLineWidth(20)
113	
114	gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300)
115	
116	writer.WriteElement(element)
117	
118	grp_obj = writer.End
119	
120	# Indicate that this form (content group) belongs to the given layer (OCG).
121	grp_obj.PutName("Subtype","Form")
122	grp_obj.Put("OC", layer)
123	grp_obj.PutRect("BBox", 0, 0, 1000, 1000)	# Set the clip box for the content.
124	
125	return grp_obj
126end
127
128# Creates some text and associate it with the text layer
129def CreateGroup3(doc, layer)
130	writer = ElementWriter.new
131	writer.Begin(doc.GetSDFDoc)
132	
133	# Create a path object in the shape of a heart.
134	builder = ElementBuilder.new
135	
136	# Begin writing a block of text
137	element = builder.CreateTextBegin(Font.Create(doc.GetSDFDoc, Font::E_times_roman), 120)
138	writer.WriteElement(element)
139	
140	element = builder.CreateTextRun("A text layer!")
141	
142	# Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
143	transform = Matrix2D.RotationMatrix(-45 * (3.1415/ 180.0))
144	transform.Concat(1, 0, 0, 1, 180, 100)
145	element.SetTextMatrix(transform)
146	
147	writer.WriteElement(element)
148	writer.WriteElement(builder.CreateTextEnd)
149	
150	grp_obj = writer.End
151	
152	# Indicate that this form (content group) belongs to the given layer (OCG).
153	grp_obj.PutName("Subtype","Form")
154	grp_obj.Put("OC", layer)
155	grp_obj.PutRect("BBox", 0, 0, 1000, 1000)   # Set the clip box for the content.
156	
157	return grp_obj
158end
159
160	PDFNet.Initialize(PDFTronLicense.Key)
161	
162	# Create three layers...
163	doc = PDFDoc.new
164	image_layer = CreateLayer(doc, "Image Layer")
165	text_layer = CreateLayer(doc, "Text Layer")
166	vector_layer = CreateLayer(doc, "Vector Layer")
167	
168	# Start a new page ------------------------------------
169	page = doc.PageCreate
170	
171	builder = ElementBuilder.new	# ElementBuilder is used to build new Element objects
172	writer = ElementWriter.new	# ElementWriter is used to write Elements to the page
173	writer.Begin(page)		# Begin writting to the page
174	
175	# Add new content to the page and associate it with one of the layers.
176	element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj))
177	writer.WriteElement(element)
178	
179	element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj))
180	writer.WriteElement(element)
181	
182	# Add the text layer to the page...
183	if false # set to true to enable 'ocmd' example.
184		# A bit more advanced example of how to create an OCMD text layer that 
185		# is visible only if text, image and path layers are all 'ON'.
186		# An example of how to set 'Visibility Policy' in OCMD.
187		ocgs = doc.CreateIndirectArray
188		ocgs.PushBack(image_layer.GetSDFObj)
189		ocgs.PushBack(vector_layer.GetSDFObj)
190		ocgs.PushBack(text_layer.GetSDFObj)
191		text_ocmd = OCMD.Create(doc, ocgs, OCMD::E_AllOn)
192		element = builder.CreateForm(CreateGroup3(doc, text_ocmd.GetSDFObj))
193	else
194		element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj))
195	end
196	writer.WriteElement(element)
197	
198	# Add some content to the page that does not belong to any layer...
199	# In this case this is a rectangle representing the page border.
200	element = builder.CreateRect(0, 0, page.GetPageWidth, page.GetPageHeight)
201	element.SetPathFill(false)
202	element.SetPathStroke(true)
203	element.GetGState.SetLineWidth(40)
204	writer.WriteElement(element)
205	
206	writer.End	# save changes to the current page
207	doc.PagePushBack(page)
208	# Set the default viewing preference to display 'Layer' tab
209	prefs = doc.GetViewPrefs
210	prefs.SetPageMode(PDFDocViewPrefs::E_UseOC)
211	
212	doc.Save($output_path + "pdf_layers.pdf", SDFDoc::E_linearized)
213	doc.Close
214	puts "Done."
215	
216	# The following is a code snippet shows how to selectively render 
217	# and export PDF layers.
218	
219	doc = PDFDoc.new($output_path + "pdf_layers.pdf")
220	doc.InitSecurityHandler
221	
222	if !doc.HasOC
223		puts "The document does not contain 'Optional Content'"
224	else
225		init_cfg = doc.GetOCGConfig
226		ctx = Context.new(init_cfg)
227		
228		pdfdraw = PDFDraw.new
229		pdfdraw.SetImageSize(1000, 1000)
230		pdfdraw.SetOCGContext(ctx)  # Render the page using the given OCG context.
231		
232		page = doc.GetPage(1)   # Get the first page in the document.
233		pdfdraw.Export(page, $output_path + "pdf_layers_default.png")
234		
235		# Disable drawing of content that is not optional (i.e. is not part of any layer).
236		ctx.SetNonOCDrawing(false)
237		
238		# Now render each layer in the input document to a separate image.
239		ocgs = doc.GetOCGs	# Get the array of all OCGs in the document.
240		if !ocgs.nil?
241			sz = ocgs.Size
242			i = 0
243			while i < sz do
244				ocg = Group.new(ocgs.GetAt(i))
245				ctx.ResetStates(false)
246				ctx.SetState(ocg, true)
247				fname = "pdf_layers_" + ocg.GetName + ".png"
248				puts fname
249				pdfdraw.Export(page, $output_path + fname)
250				i = i + 1
251			end
252		end
253
254		# Now draw content that is not part of any layer...
255		ctx.SetNonOCDrawing(true)
256		ctx.SetOCDrawMode(Context::E_NoOC)
257		pdfdraw.Export(page, $output_path + "pdf_layers_non_oc.png")
258		
259		doc.Close
260	end
261	PDFNet.Terminate
262	puts "Done."
1<?php
2//---------------------------------------------------------------------------------------
3// Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
4// Consult LICENSE.txt regarding license information.
5//---------------------------------------------------------------------------------------
6if(file_exists("../../../PDFNetC/Lib/PDFNetPHP.php"))
7include("../../../PDFNetC/Lib/PDFNetPHP.php");
8include("../../LicenseKey/PHP/LicenseKey.php");
9
10// Relative path to the folder containing test files.
11$input_path = getcwd()."/../../TestFiles/";
12$output_path = $input_path."Output/";
13
14//-----------------------------------------------------------------------------------
15// This sample demonstrates how to create layers in PDF.
16// The sample also shows how to extract and render PDF layers in documents 
17// that contain optional content groups (OCGs)
18//
19// With the introduction of PDF version 1.5 came the concept of Layers. 
20// Layers, or as they are more formally known Optional Content Groups (OCGs),
21// refer to sections of content in a PDF document that can be selectively 
22// viewed or hidden by document authors or consumers. This capability is useful 
23// in CAD drawings, layered artwork, maps, multi-language documents etc.
24// 
25// Notes: 
26// ---------------------------------------
27// - This sample is using CreateLayer() utility method to create new OCGs. 
28//   CreateLayer() is relatively basic, however it can be extended to set 
29//   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
30//   a complete listing of possible entries in OC dictionary please refer to 
31//   section 4.10 'Optional Content' in the PDF Reference Manual.
32// - The sample is grouping all layer content into separate Form XObjects. 
33//   Although using PDFNet is is also possible to specify Optional Content in 
34//   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
35//   XObjects results in PDFs that are cleaner, less-error prone, and faster 
36//   to process.
37//-----------------------------------------------------------------------------------
38
39// A utility function used to add new Content Groups (Layers) to the document.
40function CreateLayer($doc, $layer_name)
41{
42	$grp = Group::Create($doc, $layer_name);
43	$cfg = $doc->GetOCGConfig();
44	if (!$cfg->IsValid()) {
45		$cfg = OCGConfig::Create($doc, true);
46		$cfg->SetName("Default");
47	}
48
49	// Add the new OCG to the list of layers that should appear in PDF viewer GUI.
50	$layer_order_array = $cfg->GetOrder();
51	if (!$layer_order_array) {
52        	$layer_order_array = $doc->CreateIndirectArray();
53		$cfg->SetOrder($layer_order_array);
54	}
55	$layer_order_array->PushBack($grp->GetSDFObj());
56
57	return $grp;
58}
59
60// Creates some content (3 images) and associate them with the image layer
61function CreateGroup1($doc, $layer) 
62{
63	$writer = new ElementWriter();
64	$writer->Begin($doc->GetSDFDoc());
65	global $input_path;
66	// Create an Image that can be reused in the document or on the same page.		
67	$img = Image::Create($doc->GetSDFDoc(), $input_path."peppers.jpg");
68
69	$builder = new ElementBuilder();
70	$element = $builder->CreateImage($img, new Matrix2D((double)$img->GetImageWidth()/2, -145.0, 20.0, 
71							(double)$img->GetImageHeight()/2, 200.0, 150.0));
72	$writer->WritePlacedElement($element);
73
74	$gstate = $element->GetGState();	// use the same image (just change its matrix)
75	$gstate->SetTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0);
76	$writer->WritePlacedElement($element);
77
78	// use the same image again (just change its matrix).
79	$writer->WritePlacedElement($builder->CreateImage($img, 300.0, 600.0, 200.0, -150.0));
80
81	$grp_obj = $writer->End();	
82
83	// Indicate that this form (content group) belongs to the given layer (OCG).
84	$grp_obj->PutName("Subtype","Form");
85	$grp_obj->Put("OC", $layer);	
86	$grp_obj->PutRect("BBox", 0, 0, 1000, 1000);  // Set the clip box for the content.
87
88	return $grp_obj;
89}
90
91// Creates some content (a path in the shape of a heart) and associate it with the vector layer
92function CreateGroup2($doc, $layer) 
93{
94	$writer = new ElementWriter();
95	$writer->Begin($doc->GetSDFDoc());
96
97	// Create a path object in the shape of a heart.
98	$builder = new ElementBuilder();
99	$builder->PathBegin();		// start constructing the path
100	$builder->MoveTo(306, 396);
101	$builder->CurveTo(681, 771, 399.75, 864.75, 306, 771);
102	$builder->CurveTo(212.25, 864.75, -69, 771, 306, 396);
103	$builder->ClosePath();
104	$element = $builder->PathEnd(); // the path geometry is now specified.
105
106	// Set the path FILL color space and color.
107	$element->SetPathFill(true);
108	$gstate = $element->GetGState();
109	$gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK()); 
110	$gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0));  // cyan
111
112	// Set the path STROKE color space and color.
113	$element->SetPathStroke(true); 
114	$gstate->SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
115	$gstate->SetStrokeColor(new ColorPt(1.0, 0.0, 0.0));  // red
116	$gstate->SetLineWidth(20);
117
118	$gstate->SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0);
119
120	$writer->WriteElement($element);
121
122	$grp_obj = $writer->End();	
123
124	// Indicate that this form (content group) belongs to the given layer (OCG).
125	$grp_obj->PutName("Subtype","Form");
126	$grp_obj->Put("OC", $layer);
127	$grp_obj->PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
128
129	return $grp_obj;
130}
131
132// Creates some text and associate it with the text layer
133function CreateGroup3($doc, $layer) 
134{
135	$writer = new ElementWriter();
136	$writer->Begin($doc->GetSDFDoc());
137
138	// Create a path object in the shape of a heart.
139	$builder = new ElementBuilder();
140
141	// Begin writing a block of text
142	$element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 120.0);
143	$writer->WriteElement($element);
144
145	$element = $builder->CreateTextRun("A text layer!");
146
147	// Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
148	$transform = Matrix2D::RotationMatrix(-45 *  (3.1415/ 180.0));
149	$transform->Concat(1, 0, 0, 1, 180, 100);  
150	$element->SetTextMatrix($transform);
151
152	$writer->WriteElement($element);
153	$writer->WriteElement($builder->CreateTextEnd());
154
155	$grp_obj = $writer->End();	
156
157	// Indicate that this form (content group) belongs to the given layer (OCG).
158	$grp_obj->PutName("Subtype","Form");
159	$grp_obj->Put("OC", $layer);
160	$grp_obj->PutRect("BBox", 0, 0, 1000, 1000); 	// Set the clip box for the content.
161
162	return $grp_obj;
163}
164
165	PDFNet::Initialize($LicenseKey);
166	PDFNet::GetSystemFontList();    // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.
167
168	$doc = new PDFDoc();
169
170	// Create three layers...
171	$image_layer = CreateLayer($doc, "Image Layer");
172	$text_layer = CreateLayer($doc, "Text Layer");
173	$vector_layer = CreateLayer($doc, "Vector Layer");
174
175	// Start a new page ------------------------------------
176	$page = $doc->PageCreate();
177
178	$builder = new ElementBuilder();	// ElementBuilder is used to build new Element objects
179	$writer = new ElementWriter;	// ElementWriter is used to write Elements to the page	
180	$writer->Begin($page);		// Begin writing to the page
181
182	// Add new content to the page and associate it with one of the layers.
183	$element = $builder->CreateForm(CreateGroup1($doc, $image_layer->GetSDFObj()));
184	$writer->WriteElement($element);
185
186	$element = $builder->CreateForm(CreateGroup2($doc, $vector_layer->GetSDFObj()));
187	$writer->WriteElement($element);
188
189	// Add the text layer to the page...
190	if (false)  // set to true to enable 'ocmd' example.
191	{
192		// A bit more advanced example of how to create an OCMD text layer that 
193		// is visible only if text, image and path layers are all 'ON'.
194		// An example of how to set 'Visibility Policy' in OCMD.
195		$ocgs = $doc->CreateIndirectArray();
196		$ocgs->PushBack($image_layer->GetSDFObj());
197		$ocgs->PushBack($vector_layer->GetSDFObj());
198		$ocgs->PushBack($text_layer->GetSDFObj());
199		$text_ocmd = OCMD::Create($doc, $ocgs, OCMD::e_AllOn);
200		$element = $builde->CreateForm(CreateGroup3($doc, $text_ocmd->GetSDFObj()));
201	}
202	else {
203		$element = $builder->CreateForm(CreateGroup3($doc, $text_layer->GetSDFObj()));
204	}
205
206	$writer->WriteElement($element);
207
208	// Add some content to the page that does not belong to any layer...
209	// In this case this is a rectangle representing the page border.
210	$element = $builder->CreateRect(0, 0, $page->GetPageWidth(), $page->GetPageHeight());
211	$element->SetPathFill(false);
212	$element->SetPathStroke(true);
213	$element->GetGState()->SetLineWidth(40);
214	$writer->WriteElement($element);
215
216	$writer->End();  // save changes to the current page
217	$doc->PagePushBack($page);
218
219	// Set the default viewing preference to display 'Layer' tab.
220	$prefs = $doc->GetViewPrefs();
221	$prefs->SetPageMode(PDFDocViewPrefs::e_UseOC);
222
223	$doc->Save($output_path."pdf_layers.pdf", SDFDoc::e_linearized);
224	echo nl2br("Done.\n");
225
226	// The following is a code snippet shows how to selectively render 
227	// and export PDF layers.
228	
229	$doc = new PDFDoc($output_path."pdf_layers.pdf");
230	$doc->InitSecurityHandler();
231
232	if (!$doc->HasOC()) {
233		echo nl2br("The document does not contain 'Optional Content'\n");
234	}
235	else {
236		$init_cfg = $doc->GetOCGConfig();
237		$ctx = new Context($init_cfg);
238
239		$pdfdraw = new PDFDraw();
240		$pdfdraw->SetImageSize(1000, 1000);
241		$pdfdraw->SetOCGContext($ctx); // Render the page using the given OCG context.
242
243		$page = $doc->GetPage(1); // Get the first page in the document.
244		$pdfdraw->Export($page, $output_path."pdf_layers_default.png");
245
246		// Disable drawing of content that is not optional (i.e. is not part of any layer).
247		$ctx->SetNonOCDrawing(false);
248
249		// Now render each layer in the input document to a separate image.
250		$ocgs = $doc->GetOCGs(); // Get the array of all OCGs in the document.
251		if ($ocgs != null) {
252			$sz = $ocgs->Size();
253			for ($i=0; $i<$sz; ++$i) {
254				$ocg = new Group($ocgs->GetAt($i));
255				$ctx->ResetStates(false);
256				$ctx->SetState($ocg, true);
257				$fname = "pdf_layers_".$ocg->GetName().".png";
258				echo nl2br($fname."\n");
259				$pdfdraw->Export($page, $output_path.$fname);
260			}
261		}
262
263		// Now draw content that is not part of any layer...
264		$ctx->SetNonOCDrawing(true);
265		$ctx->SetOCDrawMode(Context::e_NoOC);
266		$pdfdraw->Export($page, $output_path."pdf_layers_non_oc.png");
267	}
268
269	$doc->Close();
270	PDFNet::Terminate();
271	echo nl2br("Done.\n");	
272?>
1#---------------------------------------------------------------------------------------
2# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
3# Consult LICENSE.txt regarding license information.
4#---------------------------------------------------------------------------------------
5
6import site
7site.addsitedir("../../../PDFNetC/Lib")
8import sys
9from PDFNetPython import *
10
11sys.path.append("../../LicenseKey/PYTHON")
12from LicenseKey import *
13
14#-----------------------------------------------------------------------------------
15# This sample demonstrates how to create layers in PDF.
16# The sample also shows how to extract and render PDF layers in documents 
17# that contain optional content groups (OCGs)
18#
19# With the introduction of PDF version 1.5 came the concept of Layers. 
20# Layers, or as they are more formally known Optional Content Groups (OCGs),
21# refer to sections of content in a PDF document that can be selectively 
22# viewed or hidden by document authors or consumers. This capability is useful 
23# in CAD drawings, layered artwork, maps, multi-language documents etc.
24# 
25# Notes: 
26# ---------------------------------------
27# - This sample is using CreateLayer() utility method to create new OCGs. 
28#   CreateLayer() is relatively basic, however it can be extended to set 
29#   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
30#   a complete listing of possible entries in OC dictionary please refer to 
31#   section 4.10 'Optional Content' in the PDF Reference Manual.
32# - The sample is grouping all layer content into separate Form XObjects. 
33#   Although using PDFNet is is also possible to specify Optional Content in 
34#   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
35#   XObjects results in PDFs that are cleaner, less-error prone, and faster 
36#   to process.
37#-----------------------------------------------------------------------------------
38
39# Relative path to the folder containing the test files.
40input_path = "../../TestFiles/"
41output_path = "../../TestFiles/Output/"
42
43# A utility function used to add new Content Groups (Layers) to the document.
44def CreateLayer(doc, layer_name):
45    grp = Group.Create(doc, layer_name)
46    cfg = doc.GetOCGConfig()
47    if not cfg.IsValid():
48        cfg = Config.Create(doc, True)
49        cfg.SetName("Default")
50        
51    # Add the new OCG to the list of layers that should appear in PDF viewer GUI.
52    layer_order_array = cfg.GetOrder()
53    if layer_order_array is None:
54        layer_order_array = doc.CreateIndirectArray()
55        cfg.SetOrder(layer_order_array)
56    layer_order_array.PushBack(grp.GetSDFObj())
57    return grp
58
59# Creates some content (3 images) and associate them with the image layer
60def CreateGroup1(doc, layer):
61    writer = ElementWriter()
62    writer.Begin(doc.GetSDFDoc())
63    
64    # Create an Image that can be reused in the document or on the same page.
65    img = Image.Create(doc.GetSDFDoc(), input_path + "peppers.jpg")
66    builder = ElementBuilder()
67    element = builder.CreateImage(img, Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150))
68    writer.WritePlacedElement(element)
69    
70    gstate = element.GetGState()    # use the same image (just change its matrix)
71    gstate.SetTransform(200, 0, 0, 300, 50, 450)
72    writer.WritePlacedElement(element)
73    
74    # use the same image again (just change its matrix).
75    writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150))
76    
77    grp_obj = writer.End()
78    
79    # Indicate that this form (content group) belongs to the given layer (OCG).
80    grp_obj.PutName("Subtype","Form")
81    grp_obj.Put("OC", layer)
82    grp_obj.PutRect("BBox", 0, 0, 1000, 1000)   # Set the clip box for the content.
83    
84    return grp_obj
85
86# Creates some content (a path in the shape of a heart) and associate it with the vector layer
87def CreateGroup2(doc, layer):
88    writer = ElementWriter()
89    writer.Begin(doc.GetSDFDoc())
90    
91    # Create a path object in the shape of a heart
92    builder = ElementBuilder()
93    builder.PathBegin()     # start constructing the path
94    builder.MoveTo(306, 396)
95    builder.CurveTo(681, 771, 399.75, 864.75, 306, 771)
96    builder.CurveTo(212.25, 864.75, -69, 771, 306, 396)
97    builder.ClosePath()
98    element = builder.PathEnd() # the path geometry is now specified.
99
100    # Set the path FILL color space and color.
101    element.SetPathFill(True)
102    gstate = element.GetGState()
103    gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
104    gstate.SetFillColor(ColorPt(1, 0, 0, 0))    # cyan
105    
106    # Set the path STROKE color space and color
107    element.SetPathStroke(True)
108    gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
109    gstate.SetStrokeColor(ColorPt(1, 0, 0))     # red
110    gstate.SetLineWidth(20)
111    
112    gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300)
113    
114    writer.WriteElement(element)
115    
116    grp_obj = writer.End()
117    
118    # Indicate that this form (content group) belongs to the given layer (OCG).
119    grp_obj.PutName("Subtype","Form")
120    grp_obj.Put("OC", layer)
121    grp_obj.PutRect("BBox", 0, 0, 1000, 1000)       # Set the clip box for the content.
122    
123    return grp_obj
124
125# Creates some text and associate it with the text layer
126def CreateGroup3(doc, layer):
127    writer = ElementWriter()
128    writer.Begin(doc.GetSDFDoc())
129    
130    # Create a path object in the shape of a heart.
131    builder = ElementBuilder()
132    
133    # Begin writing a block of text
134    element = builder.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 120)
135    writer.WriteElement(element)
136    
137    element = builder.CreateTextRun("A text layer!")
138    
139    # Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
140    transform = Matrix2D.RotationMatrix(-45 * (3.1415/ 180.0))
141    transform.Concat(1, 0, 0, 1, 180, 100)
142    element.SetTextMatrix(transform)
143    
144    writer.WriteElement(element)
145    writer.WriteElement(builder.CreateTextEnd())
146    
147    grp_obj = writer.End()
148    
149    # Indicate that this form (content group) belongs to the given layer (OCG).
150    grp_obj.PutName("Subtype","Form")
151    grp_obj.Put("OC", layer)
152    grp_obj.PutRect("BBox", 0, 0, 1000, 1000)   # Set the clip box for the content.
153    
154    return grp_obj
155
156def main():
157    PDFNet.Initialize(LicenseKey)
158    
159    # Create three layers...
160    doc = PDFDoc()
161    image_layer = CreateLayer(doc, "Image Layer")
162    text_layer = CreateLayer(doc, "Text Layer")
163    vector_layer = CreateLayer(doc, "Vector Layer")
164    
165    # Start a new page ------------------------------------
166    page = doc.PageCreate()
167    
168    builder = ElementBuilder()    # ElementBuilder is used to build new Element objects
169    writer = ElementWriter()      # ElementWriter is used to write Elements to the page
170    writer.Begin(page)            # Begin writting to the page
171    
172    # Add new content to the page and associate it with one of the layers.
173    element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj()))
174    writer.WriteElement(element)
175    
176    element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj()))
177    writer.WriteElement(element)
178    
179    # Add the text layer to the page...
180    if False: # set to true to enable 'ocmd' example.
181        # A bit more advanced example of how to create an OCMD text layer that 
182        # is visible only if text, image and path layers are all 'ON'.
183        # An example of how to set 'Visibility Policy' in OCMD.
184        ocgs = doc.CreateIndirectArray()
185        ocgs.PushBack(image_layer.GetSDFObj())
186        ocgs.PushBack(vector_layer.GetSDFObj())
187        ocgs.PushBack(text_layer.GetSDFObj())
188        text_ocmd = OCMD.Create(doc, ocgs, OCMD.e_AllOn)
189        element = builder.CreateForm(CreateGroup3(doc, text_ocmd.GetSDFObj()))
190    else:
191        element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj()))
192    writer.WriteElement(element)
193    
194    # Add some content to the page that does not belong to any layer...
195    # In this case this is a rectangle representing the page border.
196    element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight())
197    element.SetPathFill(False)
198    element.SetPathStroke(True)
199    element.GetGState().SetLineWidth(40)
200    writer.WriteElement(element)
201    
202    writer.End()    # save changes to the current page
203    doc.PagePushBack(page)
204    # Set the default viewing preference to display 'Layer' tab
205    prefs = doc.GetViewPrefs()
206    prefs.SetPageMode(PDFDocViewPrefs.e_UseOC)
207    
208    doc.Save(output_path + "pdf_layers.pdf", SDFDoc.e_linearized)
209    doc.Close()
210    print("Done.")
211    
212    # The following is a code snippet shows how to selectively render 
213    # and export PDF layers.
214    
215    doc = PDFDoc(output_path + "pdf_layers.pdf")
216    doc.InitSecurityHandler()
217    
218    if not doc.HasOC():
219        print("The document does not contain 'Optional Content'")
220    else:
221        init_cfg = doc.GetOCGConfig()
222        ctx = Context(init_cfg)
223        
224        pdfdraw = PDFDraw()
225        pdfdraw.SetImageSize(1000, 1000)
226        pdfdraw.SetOCGContext(ctx)  # Render the page using the given OCG context.
227        
228        page = doc.GetPage(1)   # Get the first page in the document.
229        pdfdraw.Export(page, output_path + "pdf_layers_default.png")
230        
231        # Disable drawing of content that is not optional (i.e. is not part of any layer).
232        ctx.SetNonOCDrawing(False)
233        
234        # Now render each layer in the input document to a separate image.
235        ocgs = doc.GetOCGs()    # Get the array of all OCGs in the document.
236        if ocgs is not None:
237            sz = ocgs.Size()
238            i = 0
239            while i < sz:
240                ocg = Group(ocgs.GetAt(i))
241                ctx.ResetStates(False)
242                ctx.SetState(ocg, True)
243                fname = "pdf_layers_" + ocg.GetName() + ".png"
244                print(fname)
245                pdfdraw.Export(page, output_path + fname)
246                i = i + 1
247        # Now draw content that is not part of any layer...
248        ctx.SetNonOCDrawing(True)
249        ctx.SetOCDrawMode(Context.e_NoOC)
250        pdfdraw.Export(page, output_path + "pdf_layers_non_oc.png")
251        
252        doc.Close()
253        PDFNet.Terminate()
254        print("Done.")                     
255
256if __name__ == '__main__':
257    main()
1'
2' Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3'
4
5Imports System
6
7Imports pdftron
8Imports pdftron.Common
9Imports pdftron.Filters
10Imports pdftron.SDF
11Imports PDFTRON.PDF
12Imports PDFTRON.PDF.OCG
13
14
15'-----------------------------------------------------------------------------------
16' This sample demonstrates how to create layers in PDF.
17' The sample also shows how to extract and render PDF layers in documents 
18' that contain optional content groups (OCGs)
19'
20' With the introduction of PDF version 1.5 came the concept of Layers. 
21' Layers, or as they are more formally known Optional Content Groups (OCGs),
22' refer to sections of content in a PDF document that can be selectively 
23' viewed or hidden by document authors or consumers. This capability is useful 
24' in CAD drawings, layered artwork, maps, multi-language documents etc.
25'
26' Notes: 
27' ---------------------------------------
28' - This sample is using CreateLayer() utility method to create new OCGs. 
29'   CreateLayer() is relatively basic, however it can be extended to set 
30'   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
31'   a complete listing of possible entries in OC dictionary please refer to 
32'   section 4.10 'Optional Content' in the PDF Reference Manual.
33' - The sample is grouping all layer content into separate Form XObjects. 
34'   Although using PDFNet is is also possible to specify Optional Content in 
35'   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
36'   XObjects results in PDFs that are cleaner, less-error prone, and faster 
37'   to process.
38'-----------------------------------------------------------------------------------
39
40Module PDFLayersTestVB
41	Dim pdfNetLoader As PDFNetLoader
42	Sub New()
43		pdfNetLoader = pdftron.PDFNetLoader.Instance()
44	End Sub
45
46	' Relative path to the folder containing test files.
47	Dim input_path As String = "../../../../TestFiles/"
48	Dim output_path As String = "../../../../TestFiles/Output/"
49
50	Sub Main()
51
52		PDFNet.Initialize(PDFTronLicense.Key)
53
54		Try
55			Using doc As PDFDoc = New PDFDoc
56				' Create three layers...
57				Dim image_layer As Group = CreateLayer(doc, "Image Layer")
58				Dim text_layer As Group = CreateLayer(doc, "Text Layer")
59				Dim vector_layer As Group = CreateLayer(doc, "Vector Layer")
60
61				' Start a new page ------------------------------------
62				Dim page As Page = doc.PageCreate()
63
64				Using builder As ElementBuilder = New ElementBuilder			' ElementBuilder is used to build new Element objects
65					Using writer As ElementWriter = New ElementWriter		  ' ElementWriter is used to write Elements to the page	
66						writer.Begin(page)			 ' begin writing to this page           
67
68						' Add new content to the page and associate it with one of the layers.
69						Dim element As Element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj()))
70						writer.WriteElement(element)
71
72						element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj()))
73						writer.WriteElement(element)
74
75						element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj()))
76						writer.WriteElement(element)
77
78						' Add some content to the page that does not belong to any layer...
79						' In this case this is a rectangle representing the page border.
80						element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight())
81						element.SetPathFill(False)
82						element.SetPathStroke(True)
83						element.GetGState().SetLineWidth(40)
84						writer.WriteElement(element)
85
86						writer.End()			  ' save changes to the current page
87						doc.PagePushBack(page)
88
89						doc.Save(output_path + "pdf_layers.pdf", SDF.SDFDoc.SaveOptions.e_linearized)
90
91					End Using
92				End Using
93
94			End Using
95			Console.WriteLine("Done.")
96
97		Catch ex As PDFNetException
98			Console.WriteLine(ex.Message)
99		Catch ex As Exception
100			MsgBox(ex.Message)
101		End Try
102
103
104		' The following is a code snippet shows how to selectively render 
105		' and export PDF layers.
106		Try
107			Using doc As PDFDoc = New PDFDoc(output_path + "pdf_layers.pdf")
108				doc.InitSecurityHandler()
109
110				If doc.HasOC() = False Then
111					Console.WriteLine("The document does not contain 'Optional Content'")
112				Else
113					Dim init_cfg As Config = doc.GetOCGConfig()
114					Dim ctx As Context = New Context(init_cfg)
115
116					Using pdfdraw As PDFDraw = New PDFDraw
117						pdfdraw.SetImageSize(1000, 1000)
118						pdfdraw.SetOCGContext(ctx)			 ' Render the page using the given OCG context.
119
120						Dim page As Page = doc.GetPage(1)			 ' Get the first page in the document.
121						pdfdraw.Export(page, output_path + "pdf_layers_default.png")
122
123						' Disable drawing of content that is not optional (i.e. is not part of any layer).
124						ctx.SetNonOCDrawing(False)
125
126						' Now render each layer in the input document to a separate image.
127						Dim ocgs As Obj = doc.GetOCGs()			 ' Get the array of all OCGs in the document.
128						If Not ocgs Is Nothing Then
129							Dim i As Integer = 0
130							Dim sz As Integer = ocgs.Size()
131							While (i < sz)
132								Dim ocg As Group = New Group(ocgs.GetAt(i))
133								ctx.ResetStates(False)
134								ctx.SetState(ocg, True)
135								Dim fname As String = "pdf_layers_" + ocg.GetName() + ".png"
136								Console.WriteLine(fname)
137								pdfdraw.Export(page, output_path + fname)
138								i = i + 1
139							End While
140						End If
141
142						' Now draw content that is not part of any layer...
143						ctx.SetNonOCDrawing(True)
144						ctx.SetOCDrawMode(Context.OCDrawMode.e_NoOC)
145						pdfdraw.Export(page, output_path + "pdf_layers_non_oc.png")
146					End Using
147					Console.WriteLine("Done.")
148				End If
149			End Using
150		Catch ex As PDFNetException
151			Console.WriteLine(ex.Message)
152		Catch ex As Exception
153			MsgBox(ex.Message)
154		End Try
155		PDFNet.Terminate()
156	End Sub
157
158	' A utility function used to add new Content Groups (Layers) to the document.
159	Function CreateLayer(ByRef doc As PDFDoc, ByVal layer_name As String) As Group
160
161		Dim grp As Group = Group.Create(doc, layer_name)
162		Dim cfg As Config = doc.GetOCGConfig()
163		If cfg Is Nothing Then
164			cfg = Config.Create(doc, True)
165			cfg.SetName("Default")
166		End If
167
168		' Add the new OCG to the list of layers that should appear in PDF viewer GUI.
169		Dim layer_order_array As Obj = cfg.GetOrder()
170		If layer_order_array Is Nothing Then
171			layer_order_array = doc.CreateIndirectArray()
172			cfg.SetOrder(layer_order_array)
173		End If
174		layer_order_array.PushBack(grp.GetSDFObj())
175
176		Return grp
177	End Function
178
179	' Creates some content (3 images) and associate them with the image layer
180	Function CreateGroup1(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj
181
182		Using writer As ElementWriter = New ElementWriter
183			writer.Begin(doc.GetSDFDoc())
184
185			' Create an Image that can be reused in the document or on the same page.		
186			Dim img As Image = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"))
187
188			Using builder As ElementBuilder = New ElementBuilder
189
190				Dim element As Element = builder.CreateImage(img, New Matrix2D(img.GetImageWidth() / 2, -145, 20, img.GetImageHeight() / 2, 200, 150))
191				writer.WritePlacedElement(element)
192
193				Dim gstate As GState = element.GetGState()		  ' use the same image (just change its matrix)
194				gstate.SetTransform(200, 0, 0, 300, 50, 450)
195				writer.WritePlacedElement(element)
196
197				' use the same image again (just change its matrix).
198				writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150))
199
200				Dim grp_obj As Obj = writer.End()
201
202				' Indicate that this form (content group) belongs to the given layer (OCG).
203				grp_obj.PutName("Subtype", "Form")
204				grp_obj.Put("OC", layer)
205				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.
206
207				Return grp_obj
208			End Using
209		End Using
210	End Function
211
212	' Creates some content (a path in the shape of a heart) and associate it with the vector layer
213	Function CreateGroup2(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj
214
215		Using writer As ElementWriter = New ElementWriter
216			writer.Begin(doc.GetSDFDoc())
217
218			Using builder As ElementBuilder = New ElementBuilder
219				' Create a path object in the shape of a heart.
220				builder.PathBegin()		' start constructing the path
221				builder.MoveTo(306, 396)
222				builder.CurveTo(681, 771, 399.75, 864.75, 306, 771)
223				builder.CurveTo(212.25, 864.75, -69, 771, 306, 396)
224				builder.ClosePath()
225				Dim element As Element = builder.PathEnd()		  ' the path geometry is now specified.
226
227				' Set the path FILL color space and color.
228				element.SetPathFill(True)
229				Dim gstate As GState = element.GetGState()
230				gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
231				gstate.SetFillColor(New ColorPt(1, 0, 0, 0))		' cyan
232
233				' Set the path STROKE color space and color.
234				element.SetPathStroke(True)
235				gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
236				gstate.SetStrokeColor(New ColorPt(1, 0, 0))		' red
237				gstate.SetLineWidth(20)
238
239				gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300)
240
241				writer.WriteElement(element)
242
243				Dim grp_obj As Obj = writer.End()
244
245				' Indicate that this form (content group) belongs to the given layer (OCG).
246				grp_obj.PutName("Subtype", "Form")
247				grp_obj.Put("OC", layer)
248				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.
249
250				Return grp_obj
251			End Using
252		End Using
253	End Function
254
255	' Creates some text and associate it with the text layer
256	Function CreateGroup3(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj
257
258		Using writer As ElementWriter = New ElementWriter
259			writer.Begin(doc.GetSDFDoc())
260
261			Using builder As ElementBuilder = New ElementBuilder
262
263				' Begin writing a block of text
264				Dim element As Element = builder.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 120)
265				writer.WriteElement(element)
266
267				element = builder.CreateTextRun("A text layer!")
268
269				' Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
270				Dim transform As Matrix2D = Matrix2D.RotationMatrix(-45 * (3.1415 / 180.0))
271				transform.Concat(1, 0, 0, 1, 180, 100)
272				element.SetTextMatrix(transform)
273
274				writer.WriteElement(element)
275				writer.WriteElement(builder.CreateTextEnd())
276
277				Dim grp_obj As Obj = writer.End()
278
279				' Indicate that this form (content group) belongs to the given layer (OCG).
280				grp_obj.PutName("Subtype", "Form")
281				grp_obj.Put("OC", layer)
282				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.
283
284				Return grp_obj
285			End Using
286		End Using
287	End Function
288
289End Module
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales