' ' PDFNet Copyright (c) 2001-2008 by PDFTron Systems Inc. All Rights Reserved. ' Imports System Imports pdftron Imports pdftron.Common Imports pdftron.Filters Imports pdftron.SDF Imports PDFTRON.PDF Imports PDFTRON.PDF.OCG '----------------------------------------------------------------------------------- ' This sample demonstrates how to create layers in PDF. ' The sample also shows how to extract and render PDF layers in documents ' that contain optional content groups (OCGs) ' ' With the introduction of PDF version 1.5 came the concept of Layers. ' Layers, or as they are more formally known Optional Content Groups (OCGs), ' refer to sections of content in a PDF document that can be selectively ' viewed or hidden by document authors or consumers. This capability is useful ' in CAD drawings, layered artwork, maps, multi-language documents etc. ' ' Notes: ' --------------------------------------- ' - This sample is using CreateLayer() utility method to create new OCGs. ' CreateLayer() is relatively basic, however it can be extended to set ' other optional entries in the 'OCG' and 'OCProperties' dictionary. For ' a complete listing of possible entries in OC dictionary please refer to ' section 4.10 'Optional Content' in the PDF Reference Manual. ' - The sample is grouping all layer content into separate Form XObjects. ' Although using PDFNet is is also possible to specify Optional Content in ' Content Streams (Section 4.10.2 in PDF Reference), Optional Content in ' XObjects results in PDFs that are cleaner, less-error prone, and faster ' to process. '----------------------------------------------------------------------------------- Module Module1 ' Relative path to the folder containing test files. Dim input_path As String = "../../../TestFiles/" Dim output_path As String = "../../../TestFiles/Output/" Sub Main() PDFNet.Initialize() PDFNet.SetResourcesPath("../../../../resources") Try Dim doc As PDFDoc = New PDFDoc ' Create three layers... Dim image_layer As Group = CreateLayer(doc, "Image Layer") Dim text_layer As Group = CreateLayer(doc, "Text Layer") Dim vector_layer As Group = CreateLayer(doc, "Vector Layer") ' Start a new page ------------------------------------ Dim page As Page = doc.PageCreate() Dim builder As ElementBuilder = New ElementBuilder ' ElementBuilder is used to build new Element objects Dim writer As ElementWriter = New ElementWriter ' ElementWriter is used to write Elements to the page writer.Begin(page) ' begin writing to this page ' Add new content to the page and associate it with one of the layers. Dim element As Element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj())) writer.WriteElement(element) element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj())) writer.WriteElement(element) element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj())) writer.WriteElement(element) ' Add some content to the page that does not belong to any layer... ' In this case this is a rectangle representing the page border. element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight()) element.SetPathFill(False) element.SetPathStroke(True) element.GetGState().SetLineWidth(40) writer.WriteElement(element) writer.End() ' save changes to the current page doc.PagePushBack(page) doc.Save(output_path + "pdf_layers.pdf", SDF.SDFDoc.SaveOptions.e_linearized) doc.Close() Console.WriteLine("Done.") Catch ex As PDFNetException Console.WriteLine(ex.Message) Catch ex As Exception MsgBox(ex.Message) End Try ' The following is a code snippet shows how to selectively render ' and export PDF layers. Try Dim doc As PDFDoc = New PDFDoc(output_path + "pdf_layers.pdf") doc.InitSecurityHandler() If doc.HasOC() = False Then Console.WriteLine("The document does not contain 'Optional Content'") Else Dim init_cfg As Config = doc.GetOCGConfig() Dim ctx As Context = New Context(init_cfg) Dim pdfdraw As PDFDraw = New PDFDraw pdfdraw.SetImageSize(1000, 1000) pdfdraw.SetOCGContext(ctx) ' Render the page using the given OCG context. Dim page As Page = doc.GetPage(1) ' Get the first page in the document. pdfdraw.Export(page, output_path + "pdf_layers_default.png") ' Disable drawing of content that is not optional (i.e. is not part of any layer). ctx.SetNonOCDrawing(False) ' Now render each layer in the input document to a separate image. Dim ocgs As Obj = doc.GetOCGs() ' Get the array of all OCGs in the document. If Not ocgs Is Nothing Then Dim i As Integer = 0 Dim sz As Integer = ocgs.Size() While (i < sz) Dim ocg As Group = New Group(ocgs.GetAt(i)) ctx.ResetStates(False) ctx.SetState(ocg, True) Dim fname As String = output_path + "pdf_layers_" + ocg.GetName() + ".png" Console.WriteLine(fname) pdfdraw.Export(page, fname) i = i + 1 End While End If ' Now draw content that is not part of any layer... ctx.SetNonOCDrawing(True) ctx.SetOCDrawMode(Context.OCDrawMode.e_NoOC) pdfdraw.Export(page, output_path + "pdf_layers_non_oc.png") doc.Close() Console.WriteLine("Done.") End If Catch ex As PDFNetException Console.WriteLine(ex.Message) Catch ex As Exception MsgBox(ex.Message) End Try PDFNet.Terminate() End Sub ' A utility function used to add new Content Groups (Layers) to the document. Function CreateLayer(ByRef doc As PDFDoc, ByVal layer_name As String) As Group Dim grp As Group = Group.Create(doc, layer_name) Dim cfg As Config = doc.GetOCGConfig() If cfg Is Nothing Then cfg = Config.Create(doc, True) cfg.SetName("Default") End If ' Add the new OCG to the list of layers that should appear in PDF viewer GUI. Dim layer_order_array As Obj = cfg.GetOrder() If layer_order_array Is Nothing Then layer_order_array = doc.CreateIndirectArray() cfg.SetOrder(layer_order_array) End If layer_order_array.PushBack(grp.GetSDFObj()) Return grp End Function ' Creates some content (3 images) and associate them with the image layer Function CreateGroup1(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj Dim writer As ElementWriter = New ElementWriter writer.Begin(doc.GetSDFDoc()) ' Create an Image that can be reused in the document or on the same page. Dim img As Image = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg")) Dim builder As ElementBuilder = New ElementBuilder Dim element As Element = builder.CreateImage(img, New Matrix2D(img.GetImageWidth() / 2, -145, 20, img.GetImageHeight() / 2, 200, 150)) writer.WritePlacedElement(element) Dim gstate As GState = element.GetGState() ' use the same image (just change its matrix) gstate.SetTransform(200, 0, 0, 300, 50, 450) writer.WritePlacedElement(element) ' use the same image again (just change its matrix). writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150)) Dim grp_obj As Obj = writer.End() ' Indicate that this form (content group) belongs to the given layer (OCG). grp_obj.PutName("Subtype", "Form") grp_obj.Put("OC", layer) grp_obj.PutRect("BBox", 0, 0, 1000, 1000) ' Set the clip box for the content. Return grp_obj End Function ' Creates some content (a path in the shape of a heart) and associate it with the vector layer Function CreateGroup2(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj Dim writer As ElementWriter = New ElementWriter writer.Begin(doc.GetSDFDoc()) Dim builder As ElementBuilder = New ElementBuilder ' Create a path object in the shape of a heart. builder.PathBegin() ' start constructing the path builder.MoveTo(306, 396) builder.CurveTo(681, 771, 399.75, 864.75, 306, 771) builder.CurveTo(212.25, 864.75, -69, 771, 306, 396) builder.ClosePath() Dim element As Element = builder.PathEnd() ' the path geometry is now specified. ' Set the path FILL color space and color. element.SetPathFill(True) Dim gstate As GState = element.GetGState() gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()) gstate.SetFillColor(New ColorPt(1, 0, 0, 0)) ' cyan ' Set the path STROKE color space and color. element.SetPathStroke(True) gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()) gstate.SetStrokeColor(New ColorPt(1, 0, 0)) ' red gstate.SetLineWidth(20) gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300) writer.WriteElement(element) Dim grp_obj As Obj = writer.End() ' Indicate that this form (content group) belongs to the given layer (OCG). grp_obj.PutName("Subtype", "Form") grp_obj.Put("OC", layer) grp_obj.PutRect("BBox", 0, 0, 1000, 1000) ' Set the clip box for the content. Return grp_obj End Function ' Creates some text and associate it with the text layer Function CreateGroup3(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj Dim writer As ElementWriter = New ElementWriter writer.Begin(doc.GetSDFDoc()) Dim builder As ElementBuilder = New ElementBuilder ' Begin writing a block of text Dim element As Element = builder.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 120) writer.WriteElement(element) element = builder.CreateTextRun("A text layer!") ' Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically. Dim transform As Matrix2D = Matrix2D.RotationMatrix(-45 * (3.1415 / 180.0)) transform.Concat(1, 0, 0, 1, 180, 100) element.SetTextMatrix(transform) writer.WriteElement(element) writer.WriteElement(builder.CreateTextEnd()) Dim grp_obj As Obj = writer.End() ' Indicate that this form (content group) belongs to the given layer (OCG). grp_obj.PutName("Subtype", "Form") grp_obj.Put("OC", layer) grp_obj.PutRect("BBox", 0, 0, 1000, 1000) ' Set the clip box for the content. Return grp_obj End Function End Module