PDF-XChange - Tracker PDF Viewer - TIFF-XChange - Image-XChange - XMF-XChange - Raster-XChange - Support

Moderators: Tracker Support, Paul - Tracker Supp, Chris - Tracker Supp, Vasyl-Tracker Dev Team, Ivan - Tracker Software, Sean - Tracker, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 10, 2017 12:18 pm

Using IPXC_OCContext.SetOCState() to hide Optional Content as follows:

public void HideOC(IPXV_Document doc)
{
    // Get pages from structure layer
    IPXS_PDFVariant pages = doc.CoreDoc.CosDocument.Root.Dict_Get("Pages").Dict_Get("Kids");

    // Loop through pages
    for (uint i = 0; i < pages.Count; i++)
    {
        // Get page properties
        IPXS_PDFVariant properties = pages[i].Dict_Get("Resources").Dict_Get("Properties");
        if (properties == null)
        {
            continue;
        }

        // Loop through properties
        for (uint j = 0; j < properties.Count; j++)
        {
            // Check only properties of OCG type
            IPXS_PDFVariant type = properties[j].Dict_Get("Type");
            if (type != null && type.Type == PXS_PDFVariantType.PVT_Name && type.GetName() == "OCG")
            {
                // Set visibility to false
                doc.ActiveView.PagesView.OCContext.SetOCState(doc.CoreDoc, properties[j], false);
            }
        }
    }
}


The doc parameter is obtained from an AxPXV_Control hosted inside a WindowsFormsHost in a WPF window.

  1. Do I need to call a method to update the rendering after setting the OC state?
  2. Is the UI/Editor Layers not linked to the Structures Layer in such a way, that changes in the Structures Layer automatically update the UI/Editor Layer view?
  3. Is there an alternative way to reach the desired hiding of Optional Content?
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 10, 2017 2:20 pm

Hello Woodgnome,

Your 1 and 2 guesses are right - the Editor\UI level needs to be updated manually when you make changes on the Core\Structure level.
Check out this post - probably this will help you:
viewtopic.php?f=66&t=29637#p117025

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 10, 2017 2:46 pm

So, to update the rendering of the document I figured out I can close and re-open the core document:

IPXC_Document doc = AxPXV_Control.Doc.CodeDoc;
AxPXV_Control.Doc.Close();
AxPXV_Control.OpenDocFrom(doc);

This seems to work if I am modifying IPXC_ContentItems, for example:

public void HideAllText(AxPXV_Control control)
{
    IPXC_Pages pages = control.Doc.CoreDoc.Pages;
    for (uint i = 0; i < pages.Count; i++)
    {
        bool updated = false;

        IPXC_Content content = pages[i].GetContent(PXC_ContentAccessMode.CAccessMode_FullClone);
        for (int j = (int)content.Items.Count - 1; j >= 0; j--)
        {
            IPXC_ContentItem item = content.Items[(uint)j];
            if (item.Type == PXC_CIType.CIT_Text)
            {
                IPXC_EState eState = item.GetEState();
                eState.AlphaFill = 0;
                item.SetEState(eState);
                content.Items.DeleteItems((uint)j);
                updated = true;
            }
        }

        if (updated)
        {
            pages[i].PlaceContent(content, (uint)PXC_PlaceContentFlags.PlaceContent_Replace);
        }
    }

    IPXC_Document doc = control.Doc.CoreDoc;
    control.Doc.Close();
    control.OpenDocFrom(doc);
}

1. Is there an easier/quicker/better way to force re-rendering of the updated core document? This above approach is slightly annoying, because it resets state, such as zoom and scroll.

I opted for IPXC_OCContext.SetOCState() because that's what was recommended and also because the Javascript approach will not find invalid/broken Optional Content (Javascript getOCGs() returns null) whereas the structures layer can find it.

2. Why are the changes to the Structures Layer not reflected in the Editor Layer when I re-open the document? Do I need to "commit" the changes from the Structures Layer to the core document in a similar manner to that of IPXC_Page.PlaceContent(IPXC_Content)?
Last edited by Woodgnome on Wed Oct 11, 2017 7:23 am, edited 2 times in total.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 10, 2017 2:59 pm

Hello Woodgnome,

To "tell" the Editor level that you have changed something on the Core\Structure level, the Event system is being used. Also, it's preferable to use Operations, as they work directly with Editor level and do all of that stuff for you (send events, undo\redo etc.). Though in your case working on the Core Level in an option. So to tell the Editor level to update itself you should send the http://sdkhelp.tracker-software.com/vie ... ityChanged event in your case. This will Invalidate the needed pages and panels appropriately.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Wed Oct 11, 2017 9:42 am

I updated the HideOC() method from my original post with code to trigger the e.OCG.visibilityChanged event:
public void HideOC(IPXV_Document doc)
{
    // Get pages from structure layer
    IPXS_PDFVariant pages = doc.CoreDoc.CosDocument.Root.Dict_Get("Pages").Dict_Get("Kids");

    // Loop through pages
    for (uint i = 0; i < pages.Count; i++)
    {
        // Get page properties
        IPXS_PDFVariant properties = pages[i].Dict_Get("Resources").Dict_Get("Properties");
        if (properties == null)
        {
            continue;
        }

        // Loop through properties
        for (uint j = 0; j < properties.Count; j++)
        {
            // Check only properties of OCG type
            IPXS_PDFVariant type = properties[j].Dict_Get("Type");
            if (type != null && type.Type == PXS_PDFVariantType.PVT_Name && type.GetName() == "OCG")
            {
                // Set visibility to false
                doc.ActiveView.PagesView.OCContext.SetOCState(doc.CoreDoc, properties[j], false);
            }
        }
    }

    IEvent evt = doc.EventServer.CreateNewEvent(pxvInst.Str2ID("e.OCG.visibilityChanged"));
    doc.EventServer.FireEvent(evt, doc);
}

The event e.OCG.visibilityChanged as well as e.document.invalidatePages do both get triggered (I can detect them in the AxPXV_Control.OnEvent event listener), but the optional content is still visible in the viewer.

1. Am I using the wrong IPXS_PDFVariant from the Structures Layer or otherwise calling these methods incorrectly?

Alternatively (and inspired by my testing with IPXC_Content):
As described in the PDF reference (page 196/317) Optional Content streams start with:
/OC/OCxxx BDC
where xxx is the ID that can also be obtained from the Resources IPXS_PDFVariant.

2. How can I extract the ID from the IPXC_ContentItem (to identify the exact IPXC_ContentItem that contains the optional content)?
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Wed Oct 11, 2017 1:57 pm

Hello Woodgnome,

Can you give us a sample document that we can test on?

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Wed Oct 11, 2017 2:32 pm

Sasha - Tracker Dev Team wrote:
Hello Woodgnome,

Can you give us a sample document that we can test on?

Cheers,
Alex
See attachment.

The optional content in question:
[4 0 obj]:
<</Length 84>>
stream
 Q
q
/OC /Xi0 BDC
0 0 0 rg
BT
1 0 0 1 139.55 806.62 Tm
/Xi1 12 Tf
(Test)Tj
ET
EMC
Q

endstream

Referenced in [22 0 obj] (formatted for readability):
<<
  /Type/Page
  /Parent 18 0 R
  /Resources <<
    /ProcSet[/PDF/Text]
    /Font <<
      /F2 15 0 R
      /TT8 3 0 R
      /TT6 16 0 R
      /TT4 2 0 R
      /TT2 29 0 R
      /Xi1 26 0 R
      /F0 <<
        /Type/Font
        /Subtype/Type1
        /BaseFont/Helvetica
      >>
    >>
    /ExtGState <<
      /GS1 10 0 R
      /gs0  <<
        /Type/ExtGState
        /ca 0.2
      >>
    >>
    /ColorSpace <</Cs5 5 0 R>>
    /Properties<</Xi0 23 0 R>>
  >>
  /MediaBox[0 0 595 842]
  /Rotate 0
  /CropBox[0 0 595 842]
  /Metadata 13 0 R
  /Contents[1 0 R 27 0 R 24 0 R 4 0 R 20 0 R 25 0 R 9 0 R 7 0 R]
>>

With properties [23 0 obj]:
<</Name(TesteringStamps)/Type/OCG>>
Attachments
sample.pdf
(11.76 KiB) Downloaded 16 times
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 9:54 am

Hello Woodgnome,

There is no OCProperties dictionary in the Document's Root dictionary, thus we cannot detect any OCGs without layers. Also, by using this method, you won't modify the document itself because the layer modification state is not written into the structure. We don't have the control over separate OC's.
What you can do is modify the structure directly - you won't need the PagesView.OCContext.SetOCState method for that.

Also, you will have to lock the document exclusively if you want to work on the structure level:
pdfCtl.Doc.CoreDoc.CosDocument.LockDocumentExclusive();
//...
//Your code
//...
pdfCtl.Doc.CoreDoc.CosDocument.UnlockDocumentExclusive();


Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 11:46 am

Ok.

1. Can you provide an example of how updating something in the Structures Layer can be reflected in the Editor Layer so the changes are visible to the user?

I've attached a sample PDF with layers and OCProperties defined in the Root dictionary and tried to run my HideOC() method (now with lock/unlock) on it:

public void HideOC(IPXV_Document doc)
{
    doc.CoreDoc.CosDocument.LockDocumentExclusive();

    // Get pages from structure layer
    IPXS_PDFVariant pages = doc.CoreDoc.CosDocument.Root.Dict_Get("Pages").Dict_Get("Kids");

    // Loop through pages
    for (uint i = 0; i < pages.Count; i++)
    {
        // Get page resources
        IPXS_PDFVariant resources = pages[i].Dict_Get("Resources");
        if (resources == null)
        {
            continue;
        }

        // Get resource properties
        IPXS_PDFVariant properties = resources.Dict_Get("Properties");
        if (properties == null)
        {
            continue;
        }

        // Loop through properties
        for (uint j = 0; j < properties.Count; j++)
        {
            // Check only properties of OCG type
            IPXS_PDFVariant type = properties[j].Dict_Get("Type");
            if (type != null && type.Type == PXS_PDFVariantType.PVT_Name && type.GetName() == "OCG")
            {
                // Set visibility to false
                doc.ActiveView.PagesView.OCContext.SetOCState(doc.CoreDoc, properties[j], false);
            }
        }
    }

    IEvent evt = doc.EventServer.CreateNewEvent(pxvInst.Str2ID("e.OCG.visibilityChanged"));
    doc.EventServer.FireEvent(evt, doc);

    doc.CoreDoc.CosDocument.UnlockDocumentExclusive();
}

2. This still doesn't show/hide anything - can you explain why?
Attachments
sample2.pdf
(84.71 KiB) Downloaded 13 times
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 12:05 pm

Hello Woodgnome,

As I previously said, this won't work (see my previous post):
 doc.ActiveView.PagesView.OCContext.SetOCState(doc.CoreDoc, properties[j], false);

You will have to modify the structure directly (like you are getting the needed dictionaries).

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 12:20 pm

Then why is the method even there? I assume it does something, yes? Can you provide a use case for it?
Last edited by Woodgnome on Thu Oct 12, 2017 12:26 pm, edited 1 time in total.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 12:24 pm

Hello Woodgnome,

It can change the state that has a layer whilst in your case - the layer itself is missing. As I said before, we do not support separate OCs without layers.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 12, 2017 12:37 pm

But it doesn't seem to do anything even with the second sample PDF I provided (which has OCProperties and layers that can also be viewed and shown/hidden in the PDF-XChange Editor application).

In the case of the second sample PDF, how should it be used to show/hide those OCGs? Does it even affect anything that is related to things that can be shown/hidden in the Editor Layer or just some internal PDF structure values?

If it requires saving and re-opening the document after calling SetOCState() that is an acceptable solution, I would just like to know how to properly use the method? The documentation at http://sdkhelp.tracker-software.com/view/PXV:IPXC_OCContext_SetOCState isn't particularly helpful, nor do I see any uses of it in https://github.com/tracker-software/PDFEditorSDKExamples.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Wed Oct 18, 2017 8:31 am

Hello Woodgnome,

Well, I've been investigating throughout the code - right now the only way to handle this correctly is by using the JS.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Wed Oct 18, 2017 10:39 am

Sasha - Tracker Dev Team wrote:
Well, I've been investigating throughout the code - right now the only way to handle this correctly is by using the JS.

Should I interpret this as "SetOCState() is bugged" or should your answer be read as a response to my original question?
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 19, 2017 8:08 am

Hello Woodgnome,

This should be interpreted as the SetOCState won't work for this case, as there is no correspondent methods that would update the pages view correctly - simply put - they are not available via the interfaces.
Also, the JS will work perfectly in case of layers (which you are working with now - not simple stripped OCGs) and will do all of the needed updates to the UI.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 19, 2017 9:42 am

In that case, my previous request still stands then:

Woodgnome wrote:
I would just like to know how to properly use the method? The documentation at http://sdkhelp.tracker-software.com/view/PXV:IPXC_OCContext_SetOCState isn't particularly helpful, nor do I see any uses of it in https://github.com/tracker-software/PDFEditorSDKExamples.

Can you provide a working example and use case for SetOCState()? In particular, which IPXS_PDFVariant should be provided to the method and what effects will the value of bVisible have on the document?

------------------------------------------------------------------------------------------------------------------------------------------

This may seem a pointless request to you, given my original question, but we've already established that SetOCState() is not directly applicable to my use case, nor are the alternative approaches due to the OCs not being inside a layer. As such I'm looking for possible workarounds.

I appreciate your efforts to answer my questions in context to my original problem, but ultimately it's not very helpful. I'm asking X and Y, but you're answering Z, because you make assumptions about my use case that you can't possible know the entire scope of, for example:

  • Despite having asked how/what/when SetOCState() is used (including indirectly in the thread title) I still haven't seen a working example.
  • I've asked which IPXS_PDFVariant to provide as a parameter to SetOCState() without any direct answers.
  • I've asked "How can I extract the ID from the IPXC_ContentItem", which was ignored because my provided (first) PDF sample doesn't have any OCProperties (which is completely unrelated to that question).
  • I've asked if changes in the structures layer can be reflected in the rendering of the PDF. I still don't know if that's possible, but you've mentioned events and exclusive locks on the structure layer as requirements, but no working examples. I myself have hinted at saving and re-opening the document.

I'm sorry if I come across as obnoxious or ignorant, but you provide an SDK for advanced PDF operations with documentation that is severely lacking outside the basic operations.

I've spent copious amounts of time traversing your documentation, C# metadata and testing methods in the Editor/Core/Structures layers that might be usable to me. I've read a fair amount of the PDF specification and have a basic understanding of it's components. I know how to decompress PDF files, check stream contents and manipulate PDFs in that way, but I'd prefer not to. I'm not an expect - you guys are. With my limited knowledge I can't tell if those manipulations would have unexpected side effects, because I didn't read page X or Y of the 1310 page specification, so I prefer to use the tools of someone who has (or at least someone who has read enough to implement their own PDF viewer and SDK to manipulate PDF documents).

Given the level of documentation you're (not) providing I would expect you to be liberal with your examples on your forum - I can't possibly be the only one, who would greatly appreciate this.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything  SOLVED

Thu Oct 19, 2017 11:49 am

Hello Woodgnome,

Despite having asked how/what/when SetOCState() is used (including indirectly in the thread title) I still haven't seen a working example.
I've asked which IPXS_PDFVariant to provide as a parameter to SetOCState() without any direct answers.


As for these two - good news - I took some more time searching why this does not work and found a small typo in one of the methods that Cloned the OCContext - that resulted in a behavior that the OCItems that you've altered where cleared to their previous state. The fix will be available from the next major build though (323) that should be out in a couple of weeks.
This code will work then:
pdfCtl.Doc.CoreDoc.CosDocument.LockDocument();
// Get OCGs from structure layer
IPXS_PDFVariant OCGs = pdfCtl.Doc.CoreDoc.CosDocument.Root.Dict_Get("OCProperties").Dict_Get("OCGs");

// Loop through OCGs
for (uint i = 0; i < OCGs.Count; i++)
{
   // Get separate OCG dictionary
   IPXS_PDFVariant properties = OCGs[i];
   if (properties == null)
      continue;
   // Check only properties of OCG type
   IPXS_PDFVariant type = properties.Dict_Get("Type");
   if (type != null && type.Type == PXS_PDFVariantType.PVT_Name && type.GetName() == "OCG")
   {
      // Set visibility to false
      pdfCtl.Doc.ActiveView.PagesView.OCContext.SetOCState(pdfCtl.Doc.CoreDoc, properties, false);
   }
}
pdfCtl.Doc.CoreDoc.CosDocument.UnlockDocument();
pdfCtl.Doc.ActiveView.PagesView.InvalidatePages(null);


I've asked "How can I extract the ID from the IPXC_ContentItem", which was ignored because my provided (first) PDF sample doesn't have any OCProperties (which is completely unrelated to that question).

If you mean the position in the IPXC_Content then it's simply the position in the IPXC_ContentItems array of the IPXC_Content. Note that XForms content items have their own content that can other XForms and so on.

I've asked if changes in the structures layer can be reflected in the rendering of the PDF. I still don't know if that's possible, but you've mentioned events and exclusive locks on the structure layer as requirements, but no working examples. I myself have hinted at saving and re-opening the document.


The locks themselves allow you to either correctly read or write the document's structure (that is not done on the normal occasions). There are 3 levels in the SDK - Structure level -> Core level -> Editor Level. To see the updates that were done in the Structure level in the Editor level, first the Core Level should be notified of that (if needed) and then the Editor level events or methods should be called to refresh the UI.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Thu Oct 19, 2017 4:19 pm

Thank you for the example! I will check test it when the 323 build is out.

Sasha - Tracker Dev Team wrote:
I've asked "How can I extract the ID from the IPXC_ContentItem", which was ignored because my provided (first) PDF sample doesn't have any OCProperties (which is completely unrelated to that question).

If you mean the position in the IPXC_Content then it's simply the position in the IPXC_ContentItems array of the IPXC_Content. Note that XForms content items have their own content that can other XForms and so on.


Bit of a vague question from my end, let me try to clarify:

I will use the extracted COS code from the PDF the sample.pdf PDF I attached previously as an example:

First, the page (object 22):
<<
  /Type/Page
  /Parent 18 0 R
  /Resources <<
    /ProcSet[/PDF/Text]
    /Font <<
      /F2 15 0 R
      /TT8 3 0 R
      /TT6 16 0 R
      /TT4 2 0 R
      /TT2 29 0 R
      /Xi1 26 0 R
      /F0 <<
        /Type/Font
        /Subtype/Type1
        /BaseFont/Helvetica
      >>
    >>
    /ExtGState <<
      /GS1 10 0 R
      /gs0  <<
        /Type/ExtGState
        /ca 0.2
      >>
    >>
    /ColorSpace <</Cs5 5 0 R>>
    /Properties<</Xi0 23 0 R>>
  >>
  /MediaBox[0 0 595 842]
  /Rotate 0
  /CropBox[0 0 595 842]
  /Metadata 13 0 R
  /Contents[1 0 R 27 0 R 24 0 R 4 0 R 20 0 R 25 0 R 9 0 R 7 0 R]
>>

Inside the page dictionary I have Page.Resources.Properties.Xi0, which is a reference to object 23:
<</Name(TesteringStamps)/Type/OCG>>

Examining the Page.Contents array I find references to multiple objects, one of which is object 4, a stream:
<</Length 84>>
stream
 Q
q
/OC /Xi0 BDC
0 0 0 rg
BT
1 0 0 1 139.55 806.62 Tm
/Xi1 12 Tf
(Test)Tj
ET
EMC
Q

endstream

Traversing the IPXV_Document.CoreDoc.CosDocument I can get the object 4 stream as a string or I can get the contents of it as 1 or more IPXC_ContentItems using IPXC_Page.GetContent().

If I wanted to, I could link some (maybe only optional/marked content, I am not sure) of these IPXC_ContentItems to their corresponding CosDocument dictionary item by parsing the stream string, for example:

  • /OC /Xi0 => Page.Resources.Properties.Xi0
  • /Xi1 12 Tf => Page.Resources.Font.Xi1

I'm not exactly sure what /Xi0 and /Xi1 are, but my question was whether or not it's possible to obtain those from their corresponding IPXC_ContentItems? Alternatively, is there another way to link items in the CosDocument to the corresponding IPXC_ContentItems?

(If possible, either solution would allow me identify optional content in the Structures layer and remove/hide it in the Core layer regardless of OCGs being defined in the OCProperties dictionary.)

Sasha - Tracker Dev Team wrote:
I've asked if changes in the structures layer can be reflected in the rendering of the PDF. I still don't know if that's possible, but you've mentioned events and exclusive locks on the structure layer as requirements, but no working examples. I myself have hinted at saving and re-opening the document.


The locks themselves allow you to either correctly read or write the document's structure (that is not done on the normal occasions). There are 3 levels in the SDK - Structure level -> Core level -> Editor Level. To see the updates that were done in the Structure level in the Editor level, first the Core Level should be notified of that (if needed) and then the Editor level events or methods should be called to refresh the UI.

I tried removing objects in the Structure layer without luck, but I probably just went about it the wrong way (using the sample document from above again):
IPXV_Document doc = _pdfControl.Doc;

doc.CoreDoc.CosDocument.LockDocument();

// Get contents of first page from structures layer
IPXS_PDFVariant contents = doc.CoreDoc.Pages[0].PDFObject.Dict_Get("Contents");

// Remove some content
contents.RemoveItems(3, 1);

doc.CoreDoc.CosDocument.UnlockDocument();

// Trigger event to notify Core layer about structure change event - probably not the correct way, given the event is fired on the Editor layer document, hmm...
IEvent evt = doc.EventServer.CreateNewEvent(pxvInst.Str2ID("e.document.sourceChanged"));
doc.EventServer.FireEvent(evt, doc);

// Trigger event to notify Editor layer about Core doc change event
doc.ActiveView.PagesView.InvalidatePages(null);

A few questions for this sample code:

  • Is it even possible to change the content of the PDF in this way (i.e., by removing 1 or more of the referenced streams of Page.Contents)?
    • If not, is it possible to modify the content on the Structures layer in another way?
  • Is it possible to update other objects (for example, document metadata) in the structures layer directly (as in, not using one of your provided methods, such as SetOCState()) and have it update in the Editor layer?
  • Am I using the correct events?

Assuming that it is possible to directly modify the arrays/dictionaries of the CosDocument and have it update the Editor layer, the simplest answer to the above questions would probably be an example of how.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Mon Oct 23, 2017 8:06 am

Hello Woodgnome,

If possible let's take a look at that gigantic post by parts. For starters:
If I wanted to, I could link some (maybe only optional/marked content, I am not sure) of these IPXC_ContentItems to their corresponding CosDocument dictionary item by parsing the stream string, for example:

/OC /Xi0 => Page.Resources.Properties.Xi0
/Xi1 12 Tf => Page.Resources.Font.Xi1

I'm not exactly sure what /Xi0 and /Xi1 are, but my question was whether or not it's possible to obtain those from their corresponding IPXC_ContentItems? Alternatively, is there another way to link items in the CosDocument to the corresponding IPXC_ContentItems?

This will give you that dictionary:
pdfCtl.Doc.CoreDoc.CosDocument.LockDocument();
IPXC_Page page = pdfCtl.Doc.CoreDoc.Pages[0];
IPXC_Content content = page.GetContent(PXC_ContentAccessMode.CAccessMode_Readonly);
for (uint i = 0; i < content.Items.Count; i++)
{
   IPXC_ContentItem it = content.Items[i];
   if (it.Type == PXC_CIType.CIT_BeginContainer)
   {
      string tag = it.MC_Tag;
      if (tag != "")
      {
         bool bIsInline = false;
         IPXS_PDFVariant dict =  it.MC_GetDict(out bIsInline);
      }
   }
            
            
}
pdfCtl.Doc.CoreDoc.CosDocument.UnlockDocument();


So what do you want to do next?

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 24, 2017 11:36 am

I see my mistake now. I had previously tried to use MC_GetDict(), but on the following PXC_CIType.CIT_Text rather than the PXC_CIType.CIT_BeginContainer.

The example you provided is exactly what I was looking for. I've written a method to hide OC by name using your approach:

public void HideOCByName(AxPXV_Control pdfCtl, string ocName)
{
    for (uint i = 0; i < pdfCtl.Doc.CoreDoc.Pages.Count; i++)
    {
        _pdfControl.Doc.CoreDoc.CosDocument.LockDocument();

        IPXC_Page page = pdfCtl.Doc.CoreDoc.Pages[i];
        IPXC_Content content = page.GetContent(PXC_ContentAccessMode.CAccessMode_FullClone);
        bool inContainerToRemove = false;
        List<uint> itemsToRemove = new List<uint>();
        for (uint j = 0; j < content.Items.Count; j++)
        {
            IPXC_ContentItem it = content.Items[j];
            if (it.Type == PXC_CIType.CIT_BeginContainer)
            {
                string tag = it.MC_Tag;
                if (tag != "")
                {
                    bool bIsInline = false;
                    IPXS_PDFVariant dict = it.MC_GetDict(out bIsInline);
                    if (dict != null)
                    {
                        if (dict.Dict_GetName("Type", "") == "OCG" && dict.Dict_GetString("Name", "") == ocName)
                        {
                            inContainerToRemove = true;
                        }
                    }
                }
            }

            if (inContainerToRemove)
            {
                itemsToRemove.Add(j);
            }
           
            if (it.Type == PXC_CIType.CIT_EndContainer)
            {
                inContainerToRemove = false;
            }
        }

        _pdfControl.Doc.CoreDoc.CosDocument.UnlockDocument();

        if (itemsToRemove.Count > 0)
        {
            content.Items.DeleteItems(itemsToRemove.First(), (uint)itemsToRemove.Count);
            pdfCtl.Doc.CoreDoc.Pages[i].PlaceContent(content, (uint)PXC_PlaceContentFlags.PlaceContent_Replace);
            pdfCtl.Doc.InvalidatePage(i);
        }
    }
}

I just have one question for this: Can PXC_CIType.CIT_BeginContainer be nested?

---------------------------------------------------------

As for the "other half" of my previous post:

You have confirmed that it is possible to update a PDF document in the Structures layer and propagate those changes to the Core layer and Editor layer. How (I provided my attempt in the example)?
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Tue Oct 24, 2017 12:16 pm

Hello Woodgnome,

Read the CIT_BeginContainer as:
CI_MarkedContent   = CIT_BeginContainer,      // represents BDC, BMC; will be replaced by CI_Container

And yes, they can be nested.

What you can do is just save the document and try opening it - if your changes will be there - then we'll can talk about the events firing. If there won't be any changes that you have made - then you have not modified the document as you needed to.

Cheers,
Alex
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
 
Woodgnome
User
Topic Author
Posts: 12
Joined: Tue Oct 10, 2017 11:25 am

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Mon Oct 30, 2017 8:58 am

Sasha - Tracker Dev Team wrote:
What you can do is just save the document and try opening it - if your changes will be there - then we'll can talk about the events firing. If there won't be any changes that you have made - then you have not modified the document as you needed to.

Currently we're using iTextSharp to add optional content and metadata into the page metadata dictionaries - we'd like to move to using you SDK instead.

It's not really a priority right now (and I haven't been able to find the right approach yet, either), so I guess we can leave it at that for now. If/when we get back to this, I think I'll write a new topic, because it's not really related to SetOCState() anyway.
 
User avatar
Sasha - Tracker Dev Team
User
Posts: 2675
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_OCContext.SetOCState() does not seem to do anything

Mon Oct 30, 2017 2:33 pm

:)
Join us at Google+:
https://plus.google.com/+PDFXChangeEditorTS
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ

Who is online

Users browsing this forum: No registered users and 1 guest