Sample C# 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. 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