[ 
https://issues.apache.org/jira/browse/PDFBOX-2786?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14527165#comment-14527165
 ] 

Tilman Hausherr edited comment on PDFBOX-2786 at 5/4/15 8:22 PM:
-----------------------------------------------------------------

I doubt whether what you do is correct, see this from the spec:
{quote}
12.3.2.2 Explicit Destinations
Table 151 shows the allowed syntactic forms for specifying a destination 
explicitly in a PDF file. In each case, page is an indirect reference to a page 
object (except in a remote go-to action; see 12.6.4.3, “Remote Go-To Actions”).
{quote}
So you should put a page object there, not a page number. (Although I tested 
with an editor to put page number 1 and it worked). Here's some code that does 
what you need:
{code}
                COSArray destinationArray = new COSArray();
                //destinationArray.add(0, 
COSNumber.get(String.valueOf(pagenumber)));  // that was your code
                destinationArray.add(0, 
getPageForFirstBookmark(outline.getFirstChild()).getCOSObject()); // that is new
                destinationArray.add(1, COSName.getPDFName("Fit"));
{code}
and here's getPageForFirst Bookmark
{code}
    static PDPage getPageForFirstBookmark(PDOutlineItem item) throws IOException
    {
        if (item != null)
        {
            PDDestination destination = item.getDestination();
            PDAction action = item.getAction();
            if (action instanceof PDActionGoTo && destination == null)
            {
                PDActionGoTo gotoAction = (PDActionGoTo) action;
                destination = gotoAction.getDestination();
            }
            if (destination != null)
            {
                if (destination instanceof PDPageDestination)
                {
                    PDPageDestination pageDest = (PDPageDestination) 
destination;
                    return pageDest.getPage();
                }
            }
            else
            {
                return getPageForFirstBookmark(item.getFirstChild());
            }
            return getPageForFirstBookmark(item.getNextSibling());
        }
        return null;
    }
{code}
and here's a segment from the PDF
{code}
4 0 obj
<<
/Count 2
/First 10 0 R
/Last 11 0 R
/Type /Outlines
>>
endobj
5 0 obj
<<
/Count 2
/Kids [12 0 R 13 0 R]
/Type /Pages
>>
endobj

...

10 0 obj
<<
/A 14 0 R
/Parent 4 0 R
/Title (Page 2)
/Next 11 0 R
>>
endobj
11 0 obj
<<
/Title (Bookmark test)
/A 15 0 R
/Parent 4 0 R
/Prev 10 0 R
>>
endobj
12 0 obj
<<
/Annots [16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R
26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R]
/Contents 32 0 R
/MediaBox [0 0 597.543 834.372]
/Parent 5 0 R
/Resources 33 0 R
/Type /Page
>>
endobj
13 0 obj
<<
/Annots [34 0 R 35 0 R 36 0 R 37 0 R]
/Contents 38 0 R
/MediaBox [0 0 597.543 834.372]
/Parent 5 0 R
/Resources 39 0 R
/Type /Page
>>
endobj
14 0 obj
<<
/D [13 0 R /FitH 1206]
/S /GoTo
>>
endobj
15 0 obj
<<
/S /GoTo
/D [13 0 R /Fit]
>>
endobj
{code}


was (Author: tilman):
I doubt whether what you do is correct, see this from the spec:
{quote}
12.3.2.2 Explicit Destinations
Table 151 shows the allowed syntactic forms for specifying a destination 
explicitly in a PDF file. In each case, page is an indirect reference to a page 
object (except in a remote go-to action; see 12.6.4.3, “Remote Go-To Actions”).
{quote}
So you should put a page object there, not a page number. (Although I tested 
with a page number and it worked). Here's some code that does what you need:
{code}
                COSArray destinationArray = new COSArray();
                //destinationArray.add(0, 
COSNumber.get(String.valueOf(pagenumber)));  // that was your code
                destinationArray.add(0, 
getPageForFirstBookmark(outline.getFirstChild()).getCOSObject()); // that is new
                destinationArray.add(1, COSName.getPDFName("Fit"));
{code}
and here's getPageForFirst Bookmark
{code}
    static PDPage getPageForFirstBookmark(PDOutlineItem item) throws IOException
    {
        if (item != null)
        {
            PDDestination destination = item.getDestination();
            PDAction action = item.getAction();
            if (action instanceof PDActionGoTo && destination == null)
            {
                PDActionGoTo gotoAction = (PDActionGoTo) action;
                destination = gotoAction.getDestination();
            }
            if (destination != null)
            {
                if (destination instanceof PDPageDestination)
                {
                    PDPageDestination pageDest = (PDPageDestination) 
destination;
                    return pageDest.getPage();
                }
            }
            else
            {
                return getPageForFirstBookmark(item.getFirstChild());
            }
            return getPageForFirstBookmark(item.getNextSibling());
        }
        return null;
    }
{code}
and here's a segment from the PDF
{code}
4 0 obj
<<
/Count 2
/First 10 0 R
/Last 11 0 R
/Type /Outlines
>>
endobj
5 0 obj
<<
/Count 2
/Kids [12 0 R 13 0 R]
/Type /Pages
>>
endobj

...

10 0 obj
<<
/A 14 0 R
/Parent 4 0 R
/Title (Page 2)
/Next 11 0 R
>>
endobj
11 0 obj
<<
/Title (Bookmark test)
/A 15 0 R
/Parent 4 0 R
/Prev 10 0 R
>>
endobj
12 0 obj
<<
/Annots [16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R
26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R]
/Contents 32 0 R
/MediaBox [0 0 597.543 834.372]
/Parent 5 0 R
/Resources 33 0 R
/Type /Page
>>
endobj
13 0 obj
<<
/Annots [34 0 R 35 0 R 36 0 R 37 0 R]
/Contents 38 0 R
/MediaBox [0 0 597.543 834.372]
/Parent 5 0 R
/Resources 39 0 R
/Type /Page
>>
endobj
14 0 obj
<<
/D [13 0 R /FitH 1206]
/S /GoTo
>>
endobj
15 0 obj
<<
/S /GoTo
/D [13 0 R /Fit]
>>
endobj
{code}

> PDPageDestination page index off by one
> ---------------------------------------
>
>                 Key: PDFBOX-2786
>                 URL: https://issues.apache.org/jira/browse/PDFBOX-2786
>             Project: PDFBox
>          Issue Type: Bug
>          Components: PDModel
>    Affects Versions: 1.8.9, 2.0.0
>            Reporter: Johanneke Lamberink
>         Attachments: Archive.zip
>
>
> When creating a new bookmark with the same page number as an existing 
> bookmark, the resulting destination is offset by 1 compared to the old 
> destination.
> This results in the bookmark being set for the next page, which could be a 
> non-existing page.
> I've added a class with an example pdf and my own output pdf. Run with 
> argument of a path to where you have the pdf, including a trailing slash.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to