Page 1 of 1

IPXC_OCContext.SetOCState() does not seem to do anything

Posted: Tue Oct 10, 2017 12:18 pm
by Woodgnome
Using IPXC_OCContext.SetOCState() to hide Optional Content as follows:

Code: Select all

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?

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

Posted: Tue Oct 10, 2017 2:20 pm
by Sasha - Tracker Dev Team
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:
https://www.pdf-xchange.com/forum3 ... 37#p117025

Cheers,
Alex

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

Posted: Tue Oct 10, 2017 2:46 pm
by Woodgnome
So, to update the rendering of the document I figured out I can close and re-open the core document:

Code: Select all

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:

Code: Select all

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)?

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

Posted: Tue Oct 10, 2017 2:59 pm
by Sasha - Tracker Dev Team
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 https://sdkhelp.pdf-xchange.com/vie ... ityChanged event in your case. This will Invalidate the needed pages and panels appropriately.

Cheers,
Alex

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

Posted: Wed Oct 11, 2017 9:42 am
by Woodgnome
I updated the HideOC() method from my original post with code to trigger the e.OCG.visibilityChanged event:

Code: Select all

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:

Code: Select all

/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)?

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

Posted: Wed Oct 11, 2017 1:57 pm
by Sasha - Tracker Dev Team
Hello Woodgnome,

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

Cheers,
Alex

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

Posted: Wed Oct 11, 2017 2:32 pm
by Woodgnome
Sasha - Tracker Dev Team wrote:Hello Woodgnome,

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

Cheers,
Alex
See attachment.

Code: Select all

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>>

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

Posted: Thu Oct 12, 2017 9:54 am
by Sasha - Tracker Dev Team
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:

Code: Select all

pdfCtl.Doc.CoreDoc.CosDocument.LockDocumentExclusive();
//...
//Your code
//...
pdfCtl.Doc.CoreDoc.CosDocument.UnlockDocumentExclusive();
Cheers,
Alex

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

Posted: Thu Oct 12, 2017 11:46 am
by Woodgnome
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:

Code: Select all

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?

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

Posted: Thu Oct 12, 2017 12:05 pm
by Sasha - Tracker Dev Team
Hello Woodgnome,

As I previously said, this won't work (see my previous post):

Code: Select all

 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

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

Posted: Thu Oct 12, 2017 12:20 pm
by Woodgnome
Then why is the method even there? I assume it does something, yes? Can you provide a use case for it?

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

Posted: Thu Oct 12, 2017 12:24 pm
by Sasha - Tracker Dev Team
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

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

Posted: Thu Oct 12, 2017 12:37 pm
by Woodgnome
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 https://sdkhelp.pdf-xchange.com/vie ... SetOCState isn't particularly helpful, nor do I see any uses of it in https://github.com/tracker-software/PDF ... DKExamples.

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

Posted: Wed Oct 18, 2017 8:31 am
by Sasha - Tracker Dev Team
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

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

Posted: Wed Oct 18, 2017 10:39 am
by Woodgnome
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?

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

Posted: Thu Oct 19, 2017 8:08 am
by Sasha - Tracker Dev Team
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

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

Posted: Thu Oct 19, 2017 9:42 am
by Woodgnome
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 https://sdkhelp.pdf-xchange.com/vie ... SetOCState isn't particularly helpful, nor do I see any uses of it in https://github.com/tracker-software/PDF ... DKExamples.
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.

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

Posted: Thu Oct 19, 2017 11:49 am
by Sasha - Tracker Dev Team
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:

Code: Select all

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

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

Posted: Thu Oct 19, 2017 4:19 pm
by Woodgnome
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):

Code: Select all

<<
  /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:

Code: Select all

<</Name(TesteringStamps)/Type/OCG>>
Examining the Page.Contents array I find references to multiple objects, one of which is object 4, a stream:

Code: Select all

<</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):

Code: Select all

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.

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

Posted: Mon Oct 23, 2017 8:06 am
by Sasha - Tracker Dev Team
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:

Code: Select all

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

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

Posted: Tue Oct 24, 2017 11:36 am
by Woodgnome
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:

Code: Select all

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)?

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

Posted: Tue Oct 24, 2017 12:16 pm
by Sasha - Tracker Dev Team
Hello Woodgnome,

Read the CIT_BeginContainer as:

Code: Select all

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

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

Posted: Mon Oct 30, 2017 8:58 am
by Woodgnome
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.

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

Posted: Mon Oct 30, 2017 2:33 pm
by Sasha - Tracker Dev Team
:)