logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Post a reply
From:
Message:

Maximum number of characters in each post is: 32767
Bold Italic Underline   Highlight Quote Choose Language for Syntax Highlighting Insert Image Insert an existing Attachment or upload a new File... Create Link   Unordered List Ordered List   Left Justify Center Justify Right Justify   Outdent Indent   More BBCode Tags
Font Color Font Size
Security Image:
Enter The Letters From The Security Image:
  Preview Post Cancel

Last 10 Posts (In reverse order)
Bazi Posted: Wednesday, October 16, 2019 2:18:27 AM(UTC)
 
Hello Paul,
Thank you for your reply.
I do the following:
After displaying a PDF in the viewer, I start by button the code that reads out the OCG's and saves all ViewStates in a list (of viewstate).
The ViewState .Value of all OCGs is already "OFF". Although these are displayed in the PdfViewer.

If I switch the ViewState.Value of the list from "OFF" to "ON" or vice versa and the page dispose and invalidate the viewer the display flickers, but otherwise nothing changes.

Code behind the Button:
Code:
 internal void LoadOCGs()
{
    this.CheckedListBox1.Items.Clear();
    ViewStates.Clear();
    if (!pdfOCGs == null)
        pdfOCGs.Clear();
    pdfOCGs = new List<Patagames.Pdf.Net.BasicTypes.PdfTypeDictionary>();
    pdfRoot = PdfViewer1.Document.Root;
    // (Optional; PDF 1.5; required if a document contains optional content)
    // dictionary or array of dictionaries specifying the optional content
    // groups whose states determine the visibility of content controlled by this membership dictionary.

    // Note: Null values or references to deleted objects are ignored. If this entry is not
    // present, is an empty array, or contains references only to null or deleted objects, the
    // membership dictionary has no effect on the visibility of any content.

    // It may be a dictionary not an array. Please check it for other documents. 
    // All provided documents contains an array in that entry.
    var oc_prop = GetDictionary(pdfRoot, "OCProperties", null/* TODO Change to default(_) if this is not a reference type */, false);
    var ocgs = oc_prop("OCGs") as Patagames.Pdf.Net.BasicTypes.PdfTypeArray;
    var list = Patagames.Pdf.Net.BasicTypes.PdfIndirectList.FromPdfDocument(PdfViewer1.Document);
    foreach (object Item in ocgs)
    {
        var ocg = Item as Patagames.Pdf.Net.BasicTypes.PdfTypeIndirect.Direct as Patagames.Pdf.Net.BasicTypes.PdfTypeDictionary;
        // A usage dictionary describing the nature of the content controlled by
        // the group. It may be used by features that automatically control the state of the
        // group based on outside factors. See “Usage and Usage Application Dictionaries”
        // on page 380 for more information.
        var usage = GetDictionary(ocg, "Usage", list);
        // A dictionary that has a single entry, ViewState, a name that may have a
        // value of ON or OFF, indicating that the group should be set to that state when the
        // document is opened in a viewer application.
        var view = GetDictionary(usage, "view");
        Patagames.Pdf.Net.BasicTypes.PdfTypeName viewState = null/* TODO Change to default(_) if this is not a reference type */;
        if (!view.ContainsKey("viewState"))
        {
            viewState = Patagames.Pdf.Net.BasicTypes.PdfTypeName.Create("OFF");
            view.Add("viewState", viewState);
        }
        else
        {
            var t = view("viewState");
            var V = (Patagames.Pdf.Net.BasicTypes.PdfTypeName)t;
            viewState = view("viewState") as Patagames.Pdf.Net.BasicTypes.PdfTypeName;
        }
        var Name = ocg.GetStringBy("Name");
        var ni = CheckedListBox1.Items.Add(Name, viewState.Value.ToString == "OFF" ? false : true);
        ViewStates.Add(viewState);
        pdfOCGs.Add(ocg);
    }
}

Code in CheckedListbox:

Code:
private void CheckedListBox1_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
    var Test = e.CurrentValue;
    var Index = e.Index;
    var ViewState = ViewStates(Index);
    ViewStates(Index).Value = Test == CheckState.Checked ? "ON" : "OFF";
    PdfViewer1.CurrentPage.Dispose();
    PdfViewer1.ClearRenderBuffer();
    PdfViewer1.Invalidate();
}


Christian
Paul Rayman Posted: Tuesday, October 15, 2019 4:22:16 PM(UTC)
 
I assume that you should call the following after changing the dictionaries.
Code:
pdfViewer1.ClearRenderBuffer();
pdfViewer1.Invalidate();


I just added this to the code in a previous post.
Bazi Posted: Sunday, October 13, 2019 10:03:42 AM(UTC)
 
Hello Paul,
was that changed?

I get the value of viewState = OFF in Line 79 from your Code for all OCGs, even though they are visible.

Christian
darren Posted: Wednesday, June 28, 2017 1:17:56 AM(UTC)
 
Thanks Paul.

That has given me the information that I need.
Paul Rayman Posted: Tuesday, June 27, 2017 6:58:13 PM(UTC)
 
Please study the following code.
It hides all document optional contents.
Briefly, you should change the value in the View dictionary.

I have checked the code with documents were provided and it works fine.

Please Note. If the page with optional content is already displayed in the viewer, then it must be reloaded.
This can be done by calling the page.Dispose method and initiating the redrawing of the pdfViewer next. In this case, the disposed page will be automatically loaded.

Code:

public PdfTypeDictionary GetDictionary(PdfTypeDictionary parent, string entry, PdfIndirectList list = null, bool is_create = true)
{
    PdfTypeDictionary ret = null;
    if (!parent.ContainsKey(entry))
    {
        if(!is_create)
            throw new Exception(string.Format("The document does not have {0} entry", entry));

        ret = PdfTypeDictionary.Create();
        if (list != null)
        {
            list.Add(ret);
            parent.SetIndirectAt(entry, list, ret);
        }
        else
            parent.SetAt(entry, ret);
    }
    else if (parent[entry] is PdfTypeIndirect)
        ret = (parent[entry] as PdfTypeIndirect).Direct as PdfTypeDictionary;
    else if (parent[entry] is PdfTypeDictionary)
        ret = parent[entry] as PdfTypeDictionary;
    else
        throw new Exception(string.Format("'{0}' entry has unknown type", entry));

    return ret;
}

public Form1()
{
    InitializeComponent();
    PdfCommon.Initialize();

    pdfViewer1.LoadDocument(@"d:\10\axf-layer-1.pdf");
    //pdfViewer1.LoadDocument(@"d:\10\House_Plan_Final.pdf");
    //pdfViewer1.LoadDocument(@"d:\10\Layers.pdf");

    //The catalog dictionary for the PDF document contained in the file
    var root = pdfViewer1.Document.Root;

    //The document’s optional content properties dictionary (see Section 4.10.3,
    //“Configuring Optional Content”).
    //(Optional; PDF 1.5; required if a document contains optional content)
    var oc_prop = GetDictionary(root, "OCProperties", null, false);

    //dictionary or array of dictionaries specifying the optional content
    //groups whose states determine the visibility of content controlled by this membership dictionary.
    //Note: Null values or references to deleted objects are ignored. If this entry is not
    //present, is an empty array, or contains references only to null or deleted objects, the
    //membership dictionary has no effect on the visibility of any content.

    //It may be a dictionary not an array. Please check it for other documents. 
    //All provided documents contains an array in that entry.
    var ocgs = oc_prop["OCGs"] as PdfTypeArray;

    var list = PdfIndirectList.FromPdfDocument(pdfViewer1.Document);
    foreach (var item in ocgs)
    {
        var ocg = (item as PdfTypeIndirect).Direct as PdfTypeDictionary;

        //A usage dictionary describing the nature of the content controlled by
        //the group. It may be used by features that automatically control the state of the
        //group based on outside factors. See “Usage and Usage Application Dictionaries”
        //on page 380 for more information.
        var usage = GetDictionary(ocg, "Usage", list);

        //A dictionary that has a single entry, ViewState, a name that may have a
        //value of ON or OFF, indicating that the group should be set to that state when the
        //document is opened in a viewer application.
        var view = GetDictionary(usage, "View");

        PdfTypeName viewState = null;
        if (!view.ContainsKey("ViewState"))
        {
            viewState = PdfTypeName.Create("OFF");
            view.Add("ViewState", viewState);
        }
        else
            viewState = view["ViewState"] as PdfTypeName;

        viewState.Value = "OFF";
    }
    pdfViewer1.ClearRenderBuffer();
    pdfViewer1.Invalidate();
}
darren Posted: Monday, June 26, 2017 6:16:47 PM(UTC)
 
I have tried many PDF files that contain layers, and they are all essentially the same.

Typical PDF files with layers can be found here(axf-layer-1.pdf) or here(Layers.pdf) or here(House_Plan_Final.pdf).
Paul Rayman Posted: Monday, June 26, 2017 1:21:35 AM(UTC)
 
could you please provide pdf document?
darren Posted: Monday, June 26, 2017 12:37:36 AM(UTC)
 
Hi Paul,

thanks for directing me to the PDF Reference.

The document I am using as a test was generated by a CAD tool. It contains Optional Content Groups (OCG), but no Optional Content Membership Dictionaries (OCMD). I have opened it in Adobe Acrobat Reader DC and I can switch the layers off and on, and I need to work out how to do the same with PDFIUM.

In section 4.10.1 of the PDF Reference, it says

Quote:
A group is assigned a state, which is either ON or OFF. States are not themselves part of the PDF document but can be set programmatically or through the viewer user interface to change the visibility of content. When a document is first opened, the groups’ states are initialized based on the document’s default configuration dictionary...


The problem I have is that I have been unable to find how to programmatically set the OCG states to ON or OFF using PDFIUM. Is it possible to do this?
Paul Rayman Posted: Thursday, June 22, 2017 5:59:31 PM(UTC)
 
Hi,
some quotes from PDF Reference ver. 1.7. page 365.
I hope it can help you

http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf
Page
Quote:

Optional Content Membership Dictionaries

As mentioned above, content typically belongs to a single optional content group
and is visible when the group is ON and invisible when it is OFF. To express more
complex visibility policies, content should declare itself not to belong directly to
an optional content group but rather to an optional content membership dictionary, whose entries are shown in Table 4.49. (Section 4.10.2 describes how content declares its membership in a group or membership dictionary.)

TABLE 4.49 Entries in an optional content membership dictionary

Key: Type
Type: name
Value: (Required) The type of PDF object that this dictionary describes; must be OCMD for an optional content membership dictionary.

Key: OCGs
Type: dictionary or array
Name: (Optional) A dictionary or array of dictionaries specifying the optional content groups whose states determine the visibility of content controlled by this member ship dictionary.

Key: P
Type: name
Name: (Optional) A name specifying the visibility policy for content belonging to this membership dictionary. Valid values are:
    AllOn: visible only if all of the entries in OCGs are ON
  • AnyOn: visible if any of the entries in OCGs are ON
  • AnyOff: visible if any of the entries in OCGs are OFF
  • AllOff: visible only if all of the entries in OCGs are OFF
Default value: AnyOn

Key: VE
Type: array
Name: (Optional; PDF 1.6) An array specifying a visibility expression, used to compute visibility of content based on a set of optional content groups; see discussion below.




An optional content membership dictionary can express its visibility policy in two ways:

  • The P entry specifies a simple boolean expression indicating how the optional content groups specified by the OCGs entry determine the visibility of content controlled by the membership dictionary.
  • PDF 1.6 introduces the VE entry, which is a visibility expression that can specify an arbitrary boolean expression for computing the visibility of content from the states of optional content groups.


Note: Since the VE entry is more general, if it is present and supported by the PDF
consumer software, it should be used in preference to OCGs and P. However, for
compatibility purposes, PDF creators should use OCGs and P entries where possible.
When the use of VE is necessary to express the intended behavior, OCGs and P entries should also be provided to approximate the behavior in older consumer software.

A visibility expression is an array with the following characteristics:
  • ts first element is a name representing a boolean operator (And, Or, or Not)
  • Subsequent elements are either optional content groups or other visibility expressions.
  • If the first element is Not, it should have only one subsequent element. If the first element is And or Or, it may have one or more subsequent elements.
  • In evaluating a visibility expression, the ON state of an optional content group is
    equated to the boolean value true; OFF is equated to false.


Membership dictionaries are useful in cases such as these:
  • Some content may choose to be invisible when a group is ON and visible when it is OFF. In this case, the content would belong to a membership dictionary whose OCGs entry consists of a single optional content group and whose P entry is AnyOff or AllOff.

    Note: It is legal to have an OCGs entry consisting of a single group and a P entry that is AnyOn or AllOn. However, in this case it is preferable to use an optional content group directly because it uses fewer objects.
  • Some content may belong to more than one group and must specify its policy when the groups are in conflicting states. In this case, the content would belong to a membership dictionary whose OCGs entry consists of an array of optional content groups and whose P entry specifies the visibility policy, as illustrated in Example 4.32 below. (Example 4.33 shows the equivalent policy using visibility expressions.)

darren Posted: Monday, June 19, 2017 7:00:40 PM(UTC)
 
My understanding is that PDF files do not support "layers" in the same way that CAD files do, but they do support "optional content" which enables a similar result. I need to be able to select which PDF layers are displayed by the PdfViewer.

I have managed to read the layers from the PDF using the following code:

Code:
   PdfTypeDictionary root = pdfViewer1.Document.Root;
   PdfTypeDictionary oc_prop = root["OCProperties"] as PdfTypeDictionary;
   PdfTypeArray ocgs = oc_prop["OCGs"] as PdfTypeArray;
   foreach (PdfTypeBase ocg_indirect in ocgs)
   {
      PdfTypeBase ocg = (ocg_indirect as PdfTypeIndirect).Direct;
      PdfTypeString name = (ocg as PdfTypeDictionary)["Name"] as PdfTypeString;
      System.Diagnostics.Debug.WriteLine(name.UnicodeString);
   }



My question is how do I control which are visible?