Sample Obj-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 iOS SDK.
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#import <OBJC/PDFNetOBJC.h>
7#import <Foundation/Foundation.h>
8
9//-----------------------------------------------------------------------------------
10// This sample demonstrates how to create layers in PDF.
11// The sample also shows how to extract and render PDF layers in documents
12// that contain optional content groups (OCGs)
13//
14// With the introduction of PDF version 1.5 came the concept of Layers.
15// Layers, or as they are more formally known Optional Content Groups (OCGs),
16// refer to sections of content in a PDF document that can be selectively
17// viewed or hidden by document authors or consumers. This capability is useful
18// in CAD drawings, layered artwork, maps, multi-language documents etc.
19//
20// Notes:
21// ---------------------------------------
22// - This sample is using CreateLayer() utility method to create new OCGs.
23// CreateLayer() is relatively basic, however it can be extended to set
24// other optional entries in the 'OCG' and 'OCProperties' dictionary. For
25// a complete listing of possible entries in OC dictionary please refer to
26// section 4.10 'Optional Content' in the PDF Reference Manual.
27// - The sample is grouping all layer content into separate Form XObjects.
28// Although using PDFNet is is also possible to specify Optional Content in
29// Content Streams (Section 4.10.2 in PDF Reference), Optional Content in
30// XObjects results in PDFs that are cleaner, less-error prone, and faster
31// to process.
32//-----------------------------------------------------------------------------------
33
34PTObj * CreateGroup1(PTPDFDoc *doc, PTObj * layer);
35PTObj * CreateGroup2(PTPDFDoc *doc, PTObj * layer);
36PTObj * CreateGroup3(PTPDFDoc *doc, PTObj * layer);
37PTGroup *CreateLayer(PTPDFDoc *doc, NSString *layer_name);
38
39int main(int argc, char *argv[])
40{
41 @autoreleasepool {
42 int ret = 0;
43 [PTPDFNet Initialize: 0];
44
45 @try
46 {
47 PTPDFDoc *doc = [[PTPDFDoc alloc] init];
48
49 // Create three layers...
50 PTGroup *image_layer = CreateLayer(doc, @"Image Layer");
51 PTGroup *text_layer = CreateLayer(doc, @"Text Layer");
52 PTGroup *vector_layer = CreateLayer(doc, @"Vector Layer");
53
54 // Start a new page ------------------------------------
55 PTPage *page = [doc PageCreate: [[PTPDFRect alloc] initWithX1: 0 y1: 0 x2: 612 y2:792]];
56
57 PTElementBuilder *builder = [[PTElementBuilder alloc] init]; // ElementBuilder is used to build new Element objects
58 PTElementWriter *writer= [[PTElementWriter alloc] init]; // ElementWriter is used to write Elements to the page
59 [writer WriterBeginWithPage: page placement: e_ptoverlay page_coord_sys: YES compress: YES resources: NULL]; // Begin writing to the page
60
61 // Add new content to the page and associate it with one of the layers.
62 PTElement *element = [builder CreateFormWithObj: CreateGroup1(doc, [image_layer GetSDFObj])];
63 [writer WriteElement: element];
64
65 element = [builder CreateFormWithObj: CreateGroup2(doc, [vector_layer GetSDFObj])];
66 [writer WriteElement: element];
67
68 // Add the text layer to the page...
69 if (NO) // set to true to enable 'ocmd' example.
70 {
71 // A bit more advanced example of how to create an OCMD text layer that
72 // is visible only if text, image and path layers are all 'ON'.
73 // An example of how to set 'Visibility Policy' in OCMD.
74 PTObj * ocgs = [doc CreateIndirectArray];
75 [ocgs PushBack: [image_layer GetSDFObj]];
76 [ocgs PushBack: [vector_layer GetSDFObj]];
77 [ocgs PushBack: [text_layer GetSDFObj]];
78 PTOCMD *text_ocmd = [PTOCMD Create: doc ocgs: ocgs vis_policy: e_ptAllOn];
79 element = [builder CreateFormWithObj: CreateGroup3(doc, [text_ocmd GetSDFObj])];
80 }
81 else {
82 element = [builder CreateFormWithObj: CreateGroup3(doc, [text_layer GetSDFObj])];
83 }
84 [writer WriteElement: element];
85
86 // Add some content to the page that does not belong to any layer...
87 // In this case this is a rectangle representing the page border.
88 element = [builder CreateRect: 0 y: 0 width: [page GetPageWidth: e_ptcrop] height: [page GetPageHeight: e_ptcrop]];
89 [element SetPathFill: NO];
90 [element SetPathStroke: YES];
91 [[element GetGState] SetLineWidth: 40];
92 [writer WriteElement: element];
93
94 [writer End]; // save changes to the current page
95 [doc PagePushBack: page];
96
97 // Set the default viewing preference to display 'Layer' tab.
98 PTPDFDocViewPrefs *prefs = [doc GetViewPrefs];
99 [prefs SetPageMode: e_ptUseOC];
100
101 [doc SaveToFile: @"../../TestFiles/Output/pdf_layers.pdf" flags: e_ptlinearized];
102 NSLog(@"Done.");
103 }
104 @catch(NSException *e)
105 {
106 NSLog(@"%@", e.reason);
107 ret = 1;
108 }
109
110 // The following is a code snippet shows how to selectively render
111 // and export PDF layers.
112 @try
113 {
114 PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: @"../../TestFiles/Output/pdf_layers.pdf"];
115 [doc InitSecurityHandler];
116
117 if (![doc HasOC]) {
118 NSLog(@"The document does not contain 'Optional Content'");
119 }
120 else {
121 PTConfig *init_cfg = [doc GetOCGConfig];
122 PTContext *ctx = [[PTContext alloc] initWithConfig: init_cfg];
123
124 PTPDFDraw *pdfdraw = [[PTPDFDraw alloc] initWithDpi: 92];
125 [pdfdraw SetImageSize: 1000 height: 1000 preserve_aspect_ratio: YES];
126 [pdfdraw SetOCGContext: ctx]; // Render the page using the given OCG context.
127
128 PTPage *page = [doc GetPage: 1]; // Get the first page in the document.
129 [pdfdraw Export:page filename: @"../../TestFiles/Output/pdf_layers_default.png" format: @"PNG"];
130
131 // Disable drawing of content that is not optional (i.e. is not part of any layer).
132 [ctx SetNonOCDrawing: NO];
133
134 // Now render each layer in the input document to a separate image.
135 PTObj * ocgs = [doc GetOCGs]; // Get the array of all OCGs in the document.
136 if (ocgs != 0) {
137 unsigned long i, sz = [ocgs Size];
138 for (i=0; i<sz; ++i) {
139 PTGroup *ocg = [[PTGroup alloc] initWithOcg: [ocgs GetAt: i]];
140 [ctx ResetStates: NO];
141 [ctx SetState: ocg state: YES];
142 NSLog(@"pdf_layers_%@.png", [ocg GetName]);
143 NSString* fname = [@"../../TestFiles/Output/pdf_layers_" stringByAppendingFormat: @"%@.png", [ocg GetName]];
144 [pdfdraw Export:page filename: fname format: @"PNG"];
145 }
146 }
147
148 // Now draw content that is not part of any layer...
149 [ctx SetNonOCDrawing: YES];
150 [ctx SetOCDrawMode: e_ptNoOC];
151 [pdfdraw Export:page filename: @"../../TestFiles/Output/pdf_layers_non_oc.png" format: @"PNG" ];
152 }
153
154 NSLog(@"Done.");
155 }
156 @catch(NSException *e)
157 {
158 NSLog(@"%@", e.reason);
159 ret = 1;
160 }
161 [PTPDFNet Terminate: 0];
162 return ret;
163 }
164}
165
166
167// A utility function used to add new Content Groups (Layers) to the document.
168PTGroup *CreateLayer(PTPDFDoc *doc, NSString *layer_name)
169{
170 PTGroup *grp = [PTGroup Create: doc name: layer_name];
171 PTConfig *cfg = [doc GetOCGConfig];
172 if (![cfg IsValid]) {
173 cfg = [PTConfig Create: doc default_config: YES];
174 [cfg SetName: @"Default"];
175 }
176
177 // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
178 PTObj * layer_order_array = [cfg GetOrder];
179 if (!layer_order_array) {
180 layer_order_array = [doc CreateIndirectArray];
181 [cfg SetOrder: layer_order_array];
182 }
183 [layer_order_array PushBack: [grp GetSDFObj]];
184
185 return grp;
186}
187
188// Creates some content (3 images) and associate them with the image layer
189PTObj * CreateGroup1(PTPDFDoc *doc, PTObj * layer)
190{
191 PTElementWriter *writer = [[PTElementWriter alloc] init];
192 [writer WriterBeginWithSDFDoc: [doc GetSDFDoc] compress: YES];
193
194 // Create an Image that can be reused in the document or on the same page.
195 PTImage *img = [PTImage Create: [doc GetSDFDoc] filename: @"../../TestFiles/peppers.jpg"];
196
197 PTElementBuilder *builder = [[PTElementBuilder alloc] init];
198 PTElement *element = [builder CreateImageWithMatrix: img mtx: [[PTMatrix2D alloc] initWithA: [img GetImageWidth]/2 b: -145 c: 20 d: [img GetImageHeight]/2 h: 200 v: 150]];
199 [writer WritePlacedElement: element];
200
201 PTGState *gstate = [element GetGState]; // use the same image (just change its matrix)
202 [gstate SetTransform: 200 b: 0 c: 0 d: 300 h: 50 v: 450];
203 [writer WritePlacedElement: element];
204
205 // use the same image again (just change its matrix).
206 [writer WritePlacedElement: [builder CreateImageWithCornerAndScale: img x: 300 y: 600 hscale: 200 vscale: -150]];
207
208 PTObj * grp_obj = [writer End];
209
210 // Indicate that this form (content group) belongs to the given layer (OCG).
211 [grp_obj PutName: @"Subtype" name: @"Form"];
212 [grp_obj Put: @"OC" obj: layer];
213 [grp_obj PutRect: @"BBox" x1: 0 y1: 0 x2: 1000 y2: 1000]; // Set the clip box for the content.
214
215 return grp_obj;
216}
217
218// Creates some content (a path in the shape of a heart) and associate it with the vector layer
219PTObj * CreateGroup2(PTPDFDoc *doc, PTObj * layer)
220{
221 PTElementWriter *writer = [[PTElementWriter alloc] init];
222 [writer WriterBeginWithSDFDoc: [doc GetSDFDoc] compress: YES];
223
224 // Create a path object in the shape of a heart.
225 PTElementBuilder *builder = [[PTElementBuilder alloc] init];
226 [builder PathBegin]; // start constructing the path
227 [builder MoveTo: 306 y: 396];
228 [builder CurveTo: 681 cy1: 771 cx2: 399.75 cy2: 864.75 x2: 306 y2: 771];
229 [builder CurveTo: 212.25 cy1: 864.75 cx2: -69 cy2: 771 x2: 306 y2: 396];
230 [builder ClosePath];
231 PTElement *element = [builder PathEnd]; // the path geometry is now specified.
232
233 // Set the path FILL color space and color.
234 [element SetPathFill: YES];
235 PTGState *gstate = [element GetGState];
236 [gstate SetFillColorSpace: [PTColorSpace CreateDeviceCMYK]];
237 [gstate SetFillColorWithColorPt: [[PTColorPt alloc] initWithX: 1 y: 0 z: 0 w: 0]]; // cyan
238
239 // Set the path STROKE color space and color.
240 [element SetPathStroke: YES];
241 [gstate SetStrokeColorSpace: [PTColorSpace CreateDeviceRGB]];
242 [gstate SetStrokeColorWithColorPt: [[PTColorPt alloc] initWithX: 1 y: 0 z: 0 w: 0]]; // red
243 [gstate SetLineWidth: 20];
244
245 [gstate SetTransform: 0.5 b: 0 c: 0 d: 0.5 h: 280 v: 300];
246
247 [writer WriteElement: element];
248
249 PTObj * grp_obj = [writer End];
250
251 // Indicate that this form (content group) belongs to the given layer (OCG).
252 [grp_obj PutName: @"Subtype" name: @"Form"];
253 [grp_obj Put: @"OC" obj: layer];
254 [grp_obj PutRect: @"BBox" x1: 0 y1: 0 x2: 1000 y2: 1000]; // Set the clip box for the content.
255
256 return grp_obj;
257}
258
259// Creates some text and associate it with the text layer
260PTObj * CreateGroup3(PTPDFDoc *doc, PTObj * layer)
261{
262 PTElementWriter *writer = [[PTElementWriter alloc] init];
263 [writer WriterBeginWithSDFDoc: [doc GetSDFDoc] compress: YES];
264
265 // Create a path object in the shape of a heart.
266 PTElementBuilder *builder = [[PTElementBuilder alloc] init];
267
268 // Begin writing a block of text
269 PTElement *element = [builder CreateTextBeginWithFont: [PTFont Create: [doc GetSDFDoc] type: e_pttimes_roman embed: NO] font_sz: 120];
270 [writer WriteElement: element];
271
272 element = [builder CreateTextRun: @"A text layer!"];
273
274 // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
275 PTMatrix2D *transform = [PTMatrix2D RotationMatrix: -45 * (3.1415/ 180.0)];
276 [transform Concat: 1 b: 0 c: 0 d: 1 h: 180 v: 100];
277 [element SetTextMatrixWithMatrix2D: transform];
278
279 [writer WriteElement: element];
280 [writer WriteElement: [builder CreateTextEnd]];
281
282 PTObj * grp_obj = [writer End];
283
284 // Indicate that this form (content group) belongs to the given layer (OCG).
285 [grp_obj PutName: @"Subtype" name: @"Form"];
286 [grp_obj Put: @"OC" obj: layer];
287 [grp_obj PutRect: @"BBox" x1: 0 y1: 0 x2: 1000 y2: 1000]; // Set the clip box for the content.
288
289 return grp_obj;
290}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6import PDFNet
7import Foundation
8
9//-----------------------------------------------------------------------------------
10// This sample demonstrates how to create layers in PDF.
11// The sample also shows how to extract and render PDF layers in documents
12// that contain optional content groups (OCGs)
13//
14// With the introduction of PDF version 1.5 came the concept of Layers.
15// Layers, or as they are more formally known Optional Content Groups (OCGs),
16// refer to sections of content in a PDF document that can be selectively
17// viewed or hidden by document authors or consumers. This capability is useful
18// in CAD drawings, layered artwork, maps, multi-language documents etc.
19//
20// Notes:
21// ---------------------------------------
22// - This sample is using CreateLayer() utility method to create new OCGs.
23// CreateLayer() is relatively basic, however it can be extended to set
24// other optional entries in the 'OCG' and 'OCProperties' dictionary. For
25// a complete listing of possible entries in OC dictionary please refer to
26// section 4.10 'Optional Content' in the PDF Reference Manual.
27// - The sample is grouping all layer content into separate Form XObjects.
28// Although using PDFNet is is also possible to specify Optional Content in
29// Content Streams (Section 4.10.2 in PDF Reference), Optional Content in
30// XObjects results in PDFs that are cleaner, less-error prone, and faster
31// to process.
32//-----------------------------------------------------------------------------------
33
34func runPDFLayersTest() -> Int {
35 return autoreleasepool {
36 var ret = 0
37
38
39 do {
40 try PTPDFNet.catchException {
41 let doc: PTPDFDoc = PTPDFDoc()
42
43 // Create three layers...
44 let image_layer: PTGroup = CreateLayer(doc: doc, layer_name: "Image Layer")
45 let text_layer: PTGroup = CreateLayer(doc: doc, layer_name: "Text Layer")
46 let vector_layer: PTGroup = CreateLayer(doc: doc, layer_name: "Vector Layer")
47
48 // Start a new page ------------------------------------
49 let page: PTPage = doc.pageCreate(PTPDFRect(x1: 0, y1: 0, x2: 612, y2: 792))
50
51 let builder: PTElementBuilder = PTElementBuilder() // ElementBuilder is used to build new Element objects
52 let writer: PTElementWriter = PTElementWriter() // ElementWriter is used to write Elements to the page
53 writer.writerBegin(with: page, placement: e_ptoverlay, page_coord_sys: true, compress: true, resources: nil) // Begin writing to the page
54
55 // Add new content to the page and associate it with one of the layers.
56 var element: PTElement! = builder.createForm(with: CreateGroup1(doc: doc, layer: image_layer.getSDFObj()))
57 writer.write(element)
58
59 element = builder.createForm(with: CreateGroup2(doc: doc, layer: vector_layer.getSDFObj()))
60 writer.write(element)
61
62 // Add the text layer to the page...
63 if false { // set to true to enable 'ocmd' example
64 // A bit more advanced example of how to create an OCMD text layer that
65 // is visible only if text, image and path layers are all 'ON'.
66 // An example of how to set 'Visibility Policy' in OCMD.
67// let ocgs: PTObj = doc.createIndirectArray()
68// ocgs.pushBack(image_layer.getSDFObj())
69// ocgs.pushBack(vector_layer.getSDFObj())
70// ocgs.pushBack(text_layer.getSDFObj())
71// let text_ocmd: PTOCMD = PTOCMD.create(doc, ocgs: ocgs, vis_policy: e_ptAllOn)
72// element = builder.createForm(with: CreateGroup3(doc: doc, layer: text_ocmd.getSDFObj()))
73 }
74 else {
75 element = builder.createForm(with: CreateGroup3(doc: doc, layer: text_layer.getSDFObj()))
76 }
77 writer.write(element)
78
79 // Add some content to the page that does not belong to any layer...
80 // In this case this is a rectangle representing the page border.
81 element = builder.createRect(0, y: 0, width: page.getWidth(e_ptcrop), height: page.getHeight(e_ptcrop))
82 element.setPathFill(false)
83 element.setPathStroke(true)
84 element.getGState().setLineWidth(40)
85 writer.write(element)
86
87 writer.end() // save changes to the current page
88 doc.pagePushBack(page)
89
90 // Set the default viewing preference to display 'Layer' tab.
91 let prefs: PTPDFDocViewPrefs = doc.getViewPrefs()
92 prefs.setPageMode(e_ptUseOC)
93
94 doc.save(toFile: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("pdf_layers.pdf").path, flags: e_ptlinearized.rawValue)
95 print("Done.")
96 }
97 } catch let e as NSError {
98 print("\(e)")
99 ret = 1
100 }
101
102 // The following is a code snippet shows how to selectively render
103 // and export PDF layers.
104 do {
105 try PTPDFNet.catchException {
106 let doc: PTPDFDoc = PTPDFDoc(filepath: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("pdf_layers.pdf").path)
107 doc.initSecurityHandler()
108
109 if !doc.hasOC() {
110 print("The document does not contain 'Optional Content'")
111 }
112 else {
113 let init_cfg: PTConfig = doc.getOCGConfig()
114 let ctx: PTContext = PTContext(config: init_cfg)
115
116 let pdfdraw: PTPDFDraw = PTPDFDraw(dpi: 92)
117 pdfdraw.setImageSize(1000, height: 1000, preserve_aspect_ratio: true)
118 pdfdraw.setOCGContext(ctx) // Render the page using the given OCG context.
119
120 let page: PTPage = doc.getPage(1) // Get the first page in the document.
121 pdfdraw.export(page, filename: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("pdf_layers_default.png").path, format: "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 if let ocgs: PTObj = doc.getOCGs() { // Get the array of all OCGs in the document.
128 var _: UInt = 0
129 let sz: UInt = ocgs.size()
130 for i in 0..<sz {
131 let ocg: PTGroup = PTGroup(ocg: ocgs.getAt(i))
132 ctx.resetStates(false)
133 ctx.setState(ocg, state: true)
134 //let fname: String = URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("pdf_layers_").path + ("\(ocg.getName()).png")
135 //pdfdraw.export(page, filename: fname, format: "PNG")
136 }
137 }
138
139 // Now draw content that is not part of any layer...
140 ctx.setNonOCDrawing(true)
141 ctx.setOCDrawMode(e_ptNoOC)
142 //pdfdraw.export(page, filename: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("pdf_layers_non_oc.png").path, format: "PNG")
143 }
144 print("Done.")
145 }
146 } catch let e as NSError {
147 print("\(e)")
148 ret = 1
149 }
150
151 return ret
152 }
153}
154
155// A utility function used to add new Content Groups (Layers) to the document.
156func CreateLayer(doc: PTPDFDoc, layer_name: String) -> PTGroup {
157 let grp: PTGroup = PTGroup.create(doc, name: layer_name)
158 var cfg: PTConfig = doc.getOCGConfig()
159 if !cfg.isValid() {
160 cfg = PTConfig.create(doc, default_config: true)
161 cfg.setName("Default")
162 }
163
164 // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
165 var layer_order_array: PTObj
166 if let opt_layer_order_array = cfg.getOrder() {
167 layer_order_array = opt_layer_order_array
168 } else {
169 layer_order_array = doc.createIndirectArray()
170 cfg.setOrder(layer_order_array)
171 }
172
173 layer_order_array.pushBack(grp.getSDFObj())
174
175 return grp
176}
177
178// Creates some content (3 images) and associate them with the image layer
179func CreateGroup1(doc: PTPDFDoc, layer: PTObj) -> PTObj {
180 let writer: PTElementWriter = PTElementWriter()
181 writer.writerBegin(with: doc.getSDFDoc(), compress: true)
182
183 // Create an Image that can be reused in the document or on the same page.
184 let img: PTImage = PTImage.create(doc.getSDFDoc(), filename: Bundle.main.path(forResource: "peppers", ofType: "jpg"))
185
186 let builder: PTElementBuilder = PTElementBuilder()
187 let element: PTElement = builder.createImage(withMatrix: img, mtx: PTMatrix2D(a: Double(img.getWidth() / 2), b: -145, c: 20, d: Double(img.getHeight() / 2), h: 200, v: 150))
188 writer.writePlacedElement(element)
189
190 let gstate: PTGState = element.getGState() // use the same image (just change its matrix)
191 gstate.setTransform(200, b: 0, c: 0, d: 300, h: 50, v: 450)
192 writer.writePlacedElement(element)
193
194 // use the same image again (just change its matrix).
195 writer.writePlacedElement(builder.createImage(withCornerAndScale: img, x: 300, y: 600, hscale: 200, vscale: -150))
196 let grp_obj: PTObj = writer.end()
197
198 // Indicate that this form (content group) belongs to the given layer (OCG).
199 grp_obj.putName("Subtype", name: "Form")
200 grp_obj.put("OC", obj: layer)
201 grp_obj.putRect("BBox", x1: 0, y1: 0, x2: 1000, y2: 1000) // Set the clip box for the content.
202
203 return grp_obj
204}
205
206// Creates some content (a path in the shape of a heart) and associate it with the vector layer
207func CreateGroup2(doc: PTPDFDoc, layer: PTObj) -> PTObj {
208 let writer: PTElementWriter = PTElementWriter()
209 writer.writerBegin(with: doc.getSDFDoc(), compress: true)
210
211 // Create a path object in the shape of a heart.
212 let builder: PTElementBuilder = PTElementBuilder()
213 builder.pathBegin() // start constructing the path
214 builder.move(to: 306, y: 396)
215 builder.curve(to: 681, cy1: 771, cx2: 399.75, cy2: 864.75, x2: 306, y2: 771)
216 builder.curve(to: 212.25, cy1: 864.75, cx2: -69, cy2: 771, x2: 306, y2: 396)
217 builder.closePath()
218 let element: PTElement = builder.pathEnd() // the path geometry is now specified.
219
220 // Set the path FILL color space and color.
221 element.setPathFill(true)
222 let gstate: PTGState = element.getGState()
223 gstate.setFill(PTColorSpace.createDeviceCMYK())
224 gstate.setFillColor(with: PTColorPt(x: 1, y: 0, z: 0, w: 0)) // cyan
225
226 // Set the path STROKE color space and color.
227 element.setPathStroke(true)
228
229 gstate.setStroke(PTColorSpace.createDeviceRGB())
230 gstate.setStrokeColor(with: PTColorPt(x: 1, y: 0, z: 0, w: 0)) // red
231 gstate.setLineWidth(20)
232
233 gstate.setTransform(0.5, b: 0, c: 0, d: 0.5, h: 280, v: 300)
234
235 writer.write(element)
236
237 let grp_obj: PTObj = writer.end()
238
239 // Indicate that this form (content group) belongs to the given layer (OCG).
240 grp_obj.putName("Subtype", name: "Form")
241 grp_obj.put("OC", obj: layer)
242 grp_obj.putRect("BBox", x1: 0, y1: 0, x2: 1000, y2: 1000) // Set the clip box for the content.
243
244 return grp_obj
245}
246
247// Creates some text and associate it with the text layer
248func CreateGroup3(doc: PTPDFDoc, layer: PTObj) -> PTObj {
249 let writer: PTElementWriter = PTElementWriter()
250 writer.writerBegin(with: doc.getSDFDoc(), compress: true)
251
252 // Create a path object in the shape of a heart.
253 let builder: PTElementBuilder = PTElementBuilder()
254
255 // Begin writing a block of text
256 var element: PTElement = builder.createTextBegin(with: PTFont.create(doc.getSDFDoc(), type: e_pttimes_roman, embed: false), font_sz: 120)
257 writer.write(element)
258
259 element = builder.createTextRun("A text layer!")
260
261 // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
262 let transform: PTMatrix2D = PTMatrix2D.rotationMatrix(-45 * (3.1415 / 180.0))
263 transform.concat(1, b: 0, c: 0, d: 1, h: 180, v: 100)
264 element.setTextMatrix(with: transform)
265
266 writer.write(element)
267 writer.write(builder.createTextEnd())
268
269 let grp_obj: PTObj = writer.end()
270
271 // Indicate that this form (content group) belongs to the given layer (OCG).
272 grp_obj.putName("Subtype", name: "Form")
273 grp_obj.put("OC", obj: layer)
274 grp_obj.putRect("BBox", x1: 0, y1: 0, x2: 1000, y2: 1000) // Set the clip box for the content.
275
276 return grp_obj
277}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales