Sample Java 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 Android SDK.
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples;
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener;
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
10import com.pdftron.android.pdfnetsdksamples.R;
11import com.pdftron.android.pdfnetsdksamples.util.Utils;
12import com.pdftron.common.Matrix2D;
13import com.pdftron.common.PDFNetException;
14import com.pdftron.pdf.ColorPt;
15import com.pdftron.pdf.ColorSpace;
16import com.pdftron.pdf.Element;
17import com.pdftron.pdf.ElementBuilder;
18import com.pdftron.pdf.ElementWriter;
19import com.pdftron.pdf.Font;
20import com.pdftron.pdf.GState;
21import com.pdftron.pdf.Image;
22import com.pdftron.pdf.PDFDoc;
23import com.pdftron.pdf.PDFDocViewPrefs;
24import com.pdftron.pdf.PDFDraw;
25import com.pdftron.pdf.Page;
26import com.pdftron.pdf.ocg.Config;
27import com.pdftron.pdf.ocg.Context;
28import com.pdftron.pdf.ocg.Group;
29import com.pdftron.pdf.ocg.OCMD;
30import com.pdftron.sdf.Obj;
31import com.pdftron.sdf.SDFDoc;
32
33import java.util.ArrayList;
34
35/**
36 * This sample demonstrates how to create layers in PDF.
37 * The sample also shows how to extract and render PDF layers in documents
38 * that contain optional content groups (OCGs)
39 * <p>
40 * With the introduction of PDF version 1.5 came the concept of Layers.
41 * Layers, or as they are more formally known Optional Content Groups (OCGs),
42 * refer to sections of content in a PDF document that can be selectively
43 * viewed or hidden by document authors or consumers. This capability is useful
44 * in CAD drawings, layered artwork, maps, multi-language documents etc.
45 * <p>
46 * Couple of notes regarding this sample:
47 * ---------------------------------------
48 * - This sample is using CreateLayer() utility method to create new OCGs.
49 * CreateLayer() is relatively basic, however it can be extended to set
50 * other optional entries in the 'OCG' and 'OCProperties' dictionary. For
51 * a complete listing of possible entries in OC dictionary please refer to
52 * section 4.10 'Optional Content' in the PDF Reference Manual.
53 * - The sample is grouping all layer content into separate Form XObjects.
54 * Although using PDFNet is is also possible to specify Optional Content in
55 * Content Streams (Section 4.10.2 in PDF Reference), Optional Content in
56 * XObjects results in PDFs that are cleaner, less-error prone, and faster
57 * to process.
58 */
59public class PDFLayersTest extends PDFNetSample {
60
61 private static OutputListener mOutputListener;
62
63 private static ArrayList<String> mFileList = new ArrayList<>();
64
65 public PDFLayersTest() {
66 setTitle(R.string.sample_pdflayers_title);
67 setDescription(R.string.sample_pdflayers_description);
68 }
69
70 @Override
71 public void run(OutputListener outputListener) {
72 super.run(outputListener);
73 mOutputListener = outputListener;
74 mFileList.clear();
75 printHeader(outputListener);
76
77 try (PDFDoc doc = new PDFDoc()) {
78 // Create three layers...
79 Group image_layer = createLayer(doc, "Image Layer");
80 Group text_layer = createLayer(doc, "Text Layer");
81 Group vector_layer = createLayer(doc, "Vector Layer");
82
83 // Start a new page ------------------------------------
84 Page page = doc.pageCreate();
85
86 ElementBuilder builder = new ElementBuilder(); // ElementBuilder is used to build new Element objects
87 ElementWriter writer = new ElementWriter(); // ElementWriter is used to write Elements to the page
88 writer.begin(page); // Begin writing to the page
89
90 // Add new content to the page and associate it with one of the layers.
91 Element element = builder.createForm(createGroup1(doc, image_layer.getSDFObj()));
92 writer.writeElement(element);
93
94 element = builder.createForm(createGroup2(doc, vector_layer.getSDFObj()));
95 writer.writeElement(element);
96
97 // Add the text layer to the page...
98 if (false) // set to true to enable 'ocmd' example.
99 {
100 // A bit more advanced example of how to create an OCMD text layer that
101 // is visible only if text, image and path layers are all 'ON'.
102 // An example of how to set 'Visibility Policy' in OCMD.
103 Obj ocgs = doc.createIndirectArray();
104 ocgs.pushBack(image_layer.getSDFObj());
105 ocgs.pushBack(vector_layer.getSDFObj());
106 ocgs.pushBack(text_layer.getSDFObj());
107 OCMD text_ocmd = OCMD.create(doc, ocgs, OCMD.e_AllOn);
108 element = builder.createForm(createGroup3(doc, text_ocmd.getSDFObj()));
109 } else {
110 element = builder.createForm(createGroup3(doc, text_layer.getSDFObj()));
111 }
112 writer.writeElement(element);
113
114 // Add some content to the page that does not belong to any layer...
115 // In this case this is a rectangle representing the page border.
116 element = builder.createRect(0, 0, page.getPageWidth(), page.getPageHeight());
117 element.setPathFill(false);
118 element.setPathStroke(true);
119 element.getGState().setLineWidth(40);
120 writer.writeElement(element);
121
122 writer.end(); // save changes to the current page
123 doc.pagePushBack(page);
124
125 // Set the default viewing preference to display 'Layer' tab.
126 PDFDocViewPrefs prefs = doc.getViewPrefs();
127 prefs.setPageMode(PDFDocViewPrefs.e_UseOC);
128
129 doc.save(Utils.createExternalFile("pdf_layers.pdf", mFileList).getAbsolutePath(), SDFDoc.SaveMode.LINEARIZED, null);
130 mOutputListener.println("Done.");
131 } catch (Exception e) {
132 mOutputListener.printError(e.getStackTrace());
133 }
134
135 // The following is a code snippet shows how to selectively render
136 // and export PDF layers.
137 try (PDFDoc doc = new PDFDoc(Utils.createExternalFile("pdf_layers.pdf", mFileList).getAbsolutePath())) {
138 doc.initSecurityHandler();
139
140 if (doc.hasOC() == false) {
141 mOutputListener.println("The document does not contain 'Optional Content'");
142 } else {
143 Config init_cfg = doc.getOCGConfig();
144 Context ctx = new Context(init_cfg);
145
146 PDFDraw pdfdraw = new PDFDraw();
147 pdfdraw.setImageSize(1000, 1000);
148 pdfdraw.setOCGContext(ctx); // Render the page using the given OCG context.
149
150 Page page = doc.getPage(1); // Get the first page in the document.
151 pdfdraw.export(page, Utils.createExternalFile("pdf_layers_default.png", mFileList).getAbsolutePath());
152 // output "pdf_layers_default.png"
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 != null) {
160 int i, sz = (int) ocgs.size();
161 for (i = 0; i < sz; ++i) {
162 Group ocg = new Group(ocgs.getAt(i));
163 ctx.resetStates(false);
164 ctx.setState(ocg, true);
165 String fname = "pdf_layers_" + ocg.getName() + ".png";
166 mOutputListener.println(fname);
167 pdfdraw.export(page, Utils.createExternalFile(fname, mFileList).getAbsolutePath());
168 // output "pdf_layers_" + ocg.getName() + ".png"
169 }
170 }
171
172 // Now draw content that is not part of any layer...
173 ctx.setNonOCDrawing(true);
174 ctx.setOCDrawMode(Context.e_NoOC);
175 pdfdraw.export(page, Utils.createExternalFile("pdf_layers_non_oc.png", mFileList).getAbsolutePath());
176 // output "pdf_layers_non_oc.png"
177 }
178
179 mOutputListener.println("Done.");
180 } catch (Exception e) {
181 mOutputListener.printError(e.getStackTrace());
182 }
183
184 for (String file : mFileList) {
185 addToFileList(file);
186 }
187 printFooter(outputListener);
188 }
189
190 // A utility function used to add new Content Groups (Layers) to the document.
191 static Group createLayer(PDFDoc doc, String layer_name) throws PDFNetException {
192 Group grp = Group.create(doc, layer_name);
193 Config cfg = doc.getOCGConfig();
194 if (cfg == null) {
195 cfg = Config.create(doc, true);
196 cfg.setName("Default");
197 }
198
199 // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
200 Obj layer_order_array = cfg.getOrder();
201 if (layer_order_array == null) {
202 layer_order_array = doc.createIndirectArray();
203 cfg.setOrder(layer_order_array);
204 }
205 layer_order_array.pushBack(grp.getSDFObj());
206
207 return grp;
208 }
209
210 // Creates some content (3 images) and associate them with the image layer
211 static Obj createGroup1(PDFDoc doc, Obj layer) throws PDFNetException {
212 ElementWriter writer = new ElementWriter();
213 writer.begin(doc);
214
215 // Create an Image that can be reused in the document or on the same page.
216 Image img = Image.create(doc.getSDFDoc(), (Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg").getAbsolutePath()));
217
218 ElementBuilder builder = new ElementBuilder();
219 Element element = builder.createImage(img, new Matrix2D(img.getImageWidth() / 2, -145, 20, img.getImageHeight() / 2, 200, 150));
220 writer.writePlacedElement(element);
221
222 GState gstate = element.getGState(); // use the same image (just change its matrix)
223 gstate.setTransform(200, 0, 0, 300, 50, 450);
224 writer.writePlacedElement(element);
225
226 // use the same image again (just change its matrix).
227 writer.writePlacedElement(builder.createImage(img, 300, 600, 200, -150));
228
229 Obj grp_obj = writer.end();
230
231 // Indicate that this form (content group) belongs to the given layer (OCG).
232 grp_obj.putName("Subtype", "Form");
233 grp_obj.put("OC", layer);
234 grp_obj.putRect("BBox", 0, 0, 1000, 1000); // Set the clip box for the content.
235
236 return grp_obj;
237 }
238
239 // Creates some content (a path in the shape of a heart) and associate it with the vector layer
240 static Obj createGroup2(PDFDoc doc, Obj layer) throws PDFNetException {
241 ElementWriter writer = new ElementWriter();
242 writer.begin(doc);
243
244 // Create a path object in the shape of a heart.
245 ElementBuilder builder = new ElementBuilder();
246 builder.pathBegin(); // start constructing the path
247 builder.moveTo(306, 396);
248 builder.curveTo(681, 771, 399.75, 864.75, 306, 771);
249 builder.curveTo(212.25, 864.75, -69, 771, 306, 396);
250 builder.closePath();
251 Element element = builder.pathEnd(); // the path geometry is now specified.
252
253 // Set the path FILL color space and color.
254 element.setPathFill(true);
255 GState gstate = element.getGState();
256 gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
257 gstate.setFillColor(new ColorPt(1, 0, 0, 0)); // cyan
258
259 // Set the path STROKE color space and color.
260 element.setPathStroke(true);
261 gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
262 gstate.setStrokeColor(new ColorPt(1, 0, 0)); // red
263 gstate.setLineWidth(20);
264
265 gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
266
267 writer.writeElement(element);
268
269 Obj grp_obj = writer.end();
270
271 // Indicate that this form (content group) belongs to the given layer (OCG).
272 grp_obj.putName("Subtype", "Form");
273 grp_obj.put("OC", layer);
274 grp_obj.putRect("BBox", 0, 0, 1000, 1000); // Set the clip box for the content.
275
276 return grp_obj;
277 }
278
279 // Creates some text and associate it with the text layer
280 static Obj createGroup3(PDFDoc doc, Obj layer) throws PDFNetException {
281 ElementWriter writer = new ElementWriter();
282 writer.begin(doc);
283
284 // Create a path object in the shape of a heart.
285 ElementBuilder builder = new ElementBuilder();
286
287 // Begin writing a block of text
288 Element element = builder.createTextBegin(Font.create(doc, Font.e_times_roman), 120);
289 writer.writeElement(element);
290
291 element = builder.createTextRun("A text layer!");
292
293 // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
294 Matrix2D transform = Matrix2D.rotationMatrix(-45 * (3.1415 / 180.0));
295 transform.concat(1, 0, 0, 1, 180, 100);
296 element.setTextMatrix(transform);
297
298 writer.writeElement(element);
299 writer.writeElement(builder.createTextEnd());
300
301 Obj grp_obj = writer.end();
302
303 // Indicate that this form (content group) belongs to the given layer (OCG).
304 grp_obj.putName("Subtype", "Form");
305 grp_obj.put("OC", layer);
306 grp_obj.putRect("BBox", 0, 0, 1000, 1000); // Set the clip box for the content.
307
308 return grp_obj;
309 }
310
311}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5package com.pdftron.android.pdfnetsdksamples.samples
6
7import com.pdftron.android.pdfnetsdksamples.OutputListener
8import com.pdftron.android.pdfnetsdksamples.PDFNetSample
9import com.pdftron.android.pdfnetsdksamples.R
10import com.pdftron.android.pdfnetsdksamples.util.Utils
11import com.pdftron.common.Matrix2D
12import com.pdftron.common.PDFNetException
13import com.pdftron.pdf.*
14import com.pdftron.pdf.ocg.Config
15import com.pdftron.pdf.ocg.Context
16import com.pdftron.pdf.ocg.Group
17import com.pdftron.pdf.ocg.OCMD
18import com.pdftron.sdf.Obj
19import com.pdftron.sdf.SDFDoc
20import java.util.*
21
22/**
23 * This sample demonstrates how to create layers in PDF.
24 * The sample also shows how to extract and render PDF layers in documents
25 * that contain optional content groups (OCGs)
26 *
27 *
28 * With the introduction of PDF version 1.5 came the concept of Layers.
29 * Layers, or as they are more formally known Optional Content Groups (OCGs),
30 * refer to sections of content in a PDF document that can be selectively
31 * viewed or hidden by document authors or consumers. This capability is useful
32 * in CAD drawings, layered artwork, maps, multi-language documents etc.
33 *
34 *
35 * Couple of notes regarding this sample:
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 */
48class PDFLayersTest : PDFNetSample() {
49 override fun run(outputListener: OutputListener?) {
50 super.run(outputListener)
51 mOutputListener = outputListener
52 mFileList.clear()
53 printHeader(outputListener!!)
54 try {
55 PDFDoc().use { doc ->
56 // Create three layers...
57 val image_layer = createLayer(doc, "Image Layer")
58 val text_layer = createLayer(doc, "Text Layer")
59 val vector_layer = createLayer(doc, "Vector Layer")
60
61 // Start a new page ------------------------------------
62 val page = doc.pageCreate()
63 val builder = ElementBuilder() // ElementBuilder is used to build new Element objects
64 val writer = ElementWriter() // ElementWriter is used to write Elements to the page
65 writer.begin(page) // Begin writing to the page
66
67 // Add new content to the page and associate it with one of the layers.
68 var element = builder.createForm(createGroup1(doc, image_layer.sdfObj))
69 writer.writeElement(element)
70 element = builder.createForm(createGroup2(doc, vector_layer.sdfObj))
71 writer.writeElement(element)
72
73 // Add the text layer to the page...
74 element = if (false) // set to true to enable 'ocmd' example.
75 {
76 // A bit more advanced example of how to create an OCMD text layer that
77 // is visible only if text, image and path layers are all 'ON'.
78 // An example of how to set 'Visibility Policy' in OCMD.
79 val ocgs = doc.createIndirectArray()
80 ocgs.pushBack(image_layer.sdfObj)
81 ocgs.pushBack(vector_layer.sdfObj)
82 ocgs.pushBack(text_layer.sdfObj)
83 val text_ocmd = OCMD.create(doc, ocgs, OCMD.e_AllOn)
84 builder.createForm(createGroup3(doc, text_ocmd.sdfObj))
85 } else {
86 builder.createForm(createGroup3(doc, text_layer.sdfObj))
87 }
88 writer.writeElement(element)
89
90 // Add some content to the page that does not belong to any layer...
91 // In this case this is a rectangle representing the page border.
92 element = builder.createRect(0.0, 0.0, page.pageWidth, page.pageHeight)
93 element.setPathFill(false)
94 element.setPathStroke(true)
95 element.gState.lineWidth = 40.0
96 writer.writeElement(element)
97 writer.end() // save changes to the current page
98 doc.pagePushBack(page)
99
100 // Set the default viewing preference to display 'Layer' tab.
101 val prefs = doc.viewPrefs
102 prefs.pageMode = PDFDocViewPrefs.e_UseOC
103 doc.save(Utils.createExternalFile("pdf_layers.pdf", mFileList).absolutePath, SDFDoc.SaveMode.LINEARIZED, null)
104 mOutputListener!!.println("Done.")
105 }
106 } catch (e: Exception) {
107 mOutputListener!!.printError(e.stackTrace)
108 }
109
110 // The following is a code snippet shows how to selectively render
111 // and export PDF layers.
112 try {
113 PDFDoc(Utils.createExternalFile("pdf_layers.pdf", mFileList).absolutePath).use { doc ->
114 doc.initSecurityHandler()
115 if (doc.hasOC() == false) {
116 mOutputListener!!.println("The document does not contain 'Optional Content'")
117 } else {
118 val init_cfg = doc.ocgConfig
119 val ctx = Context(init_cfg)
120 val pdfdraw = PDFDraw()
121 pdfdraw.setImageSize(1000, 1000)
122 pdfdraw.setOCGContext(ctx) // Render the page using the given OCG context.
123 val page = doc.getPage(1) // Get the first page in the document.
124 pdfdraw.export(page, Utils.createExternalFile("pdf_layers_default.png", mFileList).absolutePath)
125
126 // Disable drawing of content that is not optional (i.e. is not part of any layer).
127 ctx.setNonOCDrawing(false)
128
129 // Now render each layer in the input document to a separate image.
130 val ocgs = doc.ocGs // Get the array of all OCGs in the document.
131 if (ocgs != null) {
132 var i: Int
133 val sz = ocgs.size().toInt()
134 i = 0
135 while (i < sz) {
136 val ocg = Group(ocgs.getAt(i))
137 ctx.resetStates(false)
138 ctx.setState(ocg, true)
139 val fname = "pdf_layers_" + ocg.name + ".png"
140 mOutputListener!!.println(fname)
141 pdfdraw.export(page, Utils.createExternalFile(fname, mFileList).absolutePath)
142 ++i
143 }
144 }
145
146 // Now draw content that is not part of any layer...
147 ctx.setNonOCDrawing(true)
148 ctx.setOCDrawMode(Context.e_NoOC)
149 pdfdraw.export(page, Utils.createExternalFile("pdf_layers_non_oc.png", mFileList).absolutePath)
150 }
151 mOutputListener!!.println("Done.")
152 }
153 } catch (e: Exception) {
154 mOutputListener!!.printError(e.stackTrace)
155 }
156 for (file in mFileList) {
157 addToFileList(file)
158 }
159 printFooter(outputListener)
160 }
161
162 companion object {
163 private var mOutputListener: OutputListener? = null
164 private val mFileList = ArrayList<String>()
165
166 // A utility function used to add new Content Groups (Layers) to the document.
167 @Throws(PDFNetException::class)
168 fun createLayer(doc: PDFDoc, layer_name: String?): Group {
169 val grp = Group.create(doc, layer_name)
170 var cfg = doc.ocgConfig
171 if (cfg == null) {
172 cfg = Config.create(doc, true)
173 cfg.name = "Default"
174 }
175
176 // Add the new OCG to the list of layers that should appear in PDF viewer GUI.
177 var layer_order_array = cfg!!.order
178 if (layer_order_array == null) {
179 layer_order_array = doc.createIndirectArray()
180 cfg.order = layer_order_array
181 }
182 layer_order_array!!.pushBack(grp.sdfObj)
183 return grp
184 }
185
186 // Creates some content (3 images) and associate them with the image layer
187 @Throws(PDFNetException::class)
188 fun createGroup1(doc: PDFDoc, layer: Obj?): Obj {
189 val writer = ElementWriter()
190 writer.begin(doc)
191
192 // Create an Image that can be reused in the document or on the same page.
193 val img = Image.create(doc.sdfDoc, Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg")!!.absolutePath)
194 val builder = ElementBuilder()
195 val element = builder.createImage(img, Matrix2D((img.imageWidth / 2).toDouble(), -145.0, 20.0, (img.imageHeight / 2).toDouble(), 200.0, 150.0))
196 writer.writePlacedElement(element)
197 val gstate = element.gState // use the same image (just change its matrix)
198 gstate.setTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0)
199 writer.writePlacedElement(element)
200
201 // use the same image again (just change its matrix).
202 writer.writePlacedElement(builder.createImage(img, 300.0, 600.0, 200.0, -150.0))
203 val grp_obj = writer.end()
204
205 // Indicate that this form (content group) belongs to the given layer (OCG).
206 grp_obj.putName("Subtype", "Form")
207 grp_obj.put("OC", layer)
208 grp_obj.putRect("BBox", 0.0, 0.0, 1000.0, 1000.0) // Set the clip box for the content.
209 return grp_obj
210 }
211
212 // Creates some content (a path in the shape of a heart) and associate it with the vector layer
213 @Throws(PDFNetException::class)
214 fun createGroup2(doc: PDFDoc?, layer: Obj?): Obj {
215 val writer = ElementWriter()
216 writer.begin(doc)
217
218 // Create a path object in the shape of a heart.
219 val builder = ElementBuilder()
220 builder.pathBegin() // start constructing the path
221 builder.moveTo(306.0, 396.0)
222 builder.curveTo(681.0, 771.0, 399.75, 864.75, 306.0, 771.0)
223 builder.curveTo(212.25, 864.75, -69.0, 771.0, 306.0, 396.0)
224 builder.closePath()
225 val element = builder.pathEnd() // the path geometry is now specified.
226
227 // Set the path FILL color space and color.
228 element.setPathFill(true)
229 val gstate = element.gState
230 gstate.fillColorSpace = ColorSpace.createDeviceCMYK()
231 gstate.fillColor = ColorPt(1.0, 0.0, 0.0, 0.0) // cyan
232
233 // Set the path STROKE color space and color.
234 element.setPathStroke(true)
235 gstate.strokeColorSpace = ColorSpace.createDeviceRGB()
236 gstate.strokeColor = ColorPt(1.0, 0.0, 0.0) // red
237 gstate.lineWidth = 20.0
238 gstate.setTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0)
239 writer.writeElement(element)
240 val grp_obj = writer.end()
241
242 // Indicate that this form (content group) belongs to the given layer (OCG).
243 grp_obj.putName("Subtype", "Form")
244 grp_obj.put("OC", layer)
245 grp_obj.putRect("BBox", 0.0, 0.0, 1000.0, 1000.0) // Set the clip box for the content.
246 return grp_obj
247 }
248
249 // Creates some text and associate it with the text layer
250 @Throws(PDFNetException::class)
251 fun createGroup3(doc: PDFDoc?, layer: Obj?): Obj {
252 val writer = ElementWriter()
253 writer.begin(doc)
254
255 // Create a path object in the shape of a heart.
256 val builder = ElementBuilder()
257
258 // Begin writing a block of text
259 var element = builder.createTextBegin(Font.create(doc, Font.e_times_roman), 120.0)
260 writer.writeElement(element)
261 element = builder.createTextRun("A text layer!")
262
263 // Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
264 val transform = Matrix2D.rotationMatrix(-45 * (3.1415 / 180.0))
265 transform.concat(1.0, 0.0, 0.0, 1.0, 180.0, 100.0)
266 element.textMatrix = transform
267 writer.writeElement(element)
268 writer.writeElement(builder.createTextEnd())
269 val grp_obj = writer.end()
270
271 // Indicate that this form (content group) belongs to the given layer (OCG).
272 grp_obj.putName("Subtype", "Form")
273 grp_obj.put("OC", layer)
274 grp_obj.putRect("BBox", 0.0, 0.0, 1000.0, 1000.0) // Set the clip box for the content.
275 return grp_obj
276 }
277 }
278
279 init {
280 setTitle(R.string.sample_pdflayers_title)
281 setDescription(R.string.sample_pdflayers_description)
282 }
283}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales