Благодаря Omz, вот фрагмент кода для получения номера страницы для конечного пункта в файле PDF:

ал спецификацию Adobe PDF, а также документацию Apple по кварцу 2d для рендеринга и анализа PDF. Я также скачал Voyeur и проверил местный PDF с ним, чтобы увидеть его внутренние данные. На данный момент я могу получить каталог документов, а затем получить оттуда словарь контуров. Я вижу, что вложенные в словари контуров словаря, что есть узлы с именем "/ Dest" со значениями, такими как:

G1.1025588 и т. Д.

Мне интересно, есть ли способ использовать эти значения, чтобы получить ссылку на страницу для рендеринга, используя некоторые методы, которые я видел в таких проектах github, как Reader, вместе с документированными примерами Apple.

Обработка PDF определенно является проблемой, поэтому любая помощь будет принята с благодарностью.

 endo.anaconda10 янв. 2011 г., 21:09
интересный вопрос

Ответы на вопрос(2)

вот фрагмент кода для получения номера страницы для конечного пункта в файле PDF:

// Get Page Number from an array
- (int) getPageNumberFromArray:(CGPDFArrayRef)array ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages
{
    int pageNumber = -1;

    // Page number reference is the first element of array (el 0)
    CGPDFDictionaryRef pageDic;
    CGPDFArrayGetDictionary(array, 0, &pageDic);

    // page searching
    for (int p=1; p<=numberOfPages; p++)
    {
        CGPDFPageRef page = CGPDFDocumentGetPage(pdfDoc, p);
        if (CGPDFPageGetDictionary(page) == pageDic)
        {
            pageNumber = p;
            break;
        }
    }

    return pageNumber;
}

// Get page number from an outline. Only support "Dest" and "A" entries
- (int) getPageNumber:(CGPDFDictionaryRef)node ofPdfDoc:(CGPDFDocumentRef)pdfDoc withNumberOfPages:(int)numberOfPages
{
    int pageNumber = -1;

    CGPDFArrayRef destArray;
    CGPDFDictionaryRef dicoActions;
    if(CGPDFDictionaryGetArray(node, "Dest", &destArray))
    {
        pageNumber = [self getPageNumberFromArray:destArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages];
    }
    else if(CGPDFDictionaryGetDictionary(node, "A", &dicoActions))
    {
        const char * typeOfActionConstChar;
        CGPDFDictionaryGetName(dicoActions, "S", &typeOfActionConstChar);

        NSString * typeOfAction = [NSString stringWithUTF8String:typeOfActionConstChar];
        if([typeOfAction isEqualToString:@"GoTo"]) // only support "GoTo" entry. See PDF spec p653
        {
            CGPDFArrayRef dArray;
            if(CGPDFDictionaryGetArray(dicoActions, "D", &dArray)) 
            {
                pageNumber = [self getPageNumberFromArray:dArray ofPdfDoc:pdfDoc withNumberOfPages:numberOfPages];
            }
        }
    }

    return pageNumber;
}
Решение Вопроса

/Dest запись в словаре элементов структуры может бытьимя,строкаилимассив.

Самый простой случай, если этомассив; затем первый элемент - это объект страницы, на который указывает элемент схемы (словарь). Чтобы получить номер страницы, вам нужно перебрать все страницы документа и посмотреть, какая из них равна (==) к словарю у вас есть (CGPDFPageRefс на самом делеCGPDFDictionaryRefс). Вы также можете пройти по дереву страниц, которое немного сложнее, но может быть быстрее (не так много, как вы ожидаете, я бы здесь не оптимизировал преждевременно). Другие элементы в массиве - это позиция на странице и т. Д., Для получения дополнительной информации ищите «Явные места назначения» в спецификации PDF.

Если запись являетсяимя или жестрока, это названный пункт назначения. Вы должны сопоставить имя с пунктом назначения из каталога документов/Dests запись, которая представляет собой словарь, который содержит дерево имен. Дерево имен - это, по сути, древовидная карта, которая обеспечивает быстрый доступ к именованным значениям без необходимости считывать все данные сразу (как в обычном словаре). К сожалению, в Quartz нет прямой поддержки деревьев имен, поэтому вам придется проделать немного больше работы для рекурсивного анализа этой структуры (см. «Деревья имен» вСпецификация PDF).

Обратите внимание, что элемент структуры не обязательно имеет/Dest запись, он также может указать свое назначение через/A (действие) запись, которая немного сложнее. Однако в большинстве случаев это будет действие «GoTo», которое, по сути, является оберткой для пункта назначения.

Сопоставление имен и мест назначения также может быть сохранено в виде простого словаря. В этом случае, это в/Dests запись словаря / имен в каталоге документа. Я редко видел это, хотя, и это устарело после PDF 1.2 (текущий 1.7).

Вам определенно понадобится спецификация PDF для этого:http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf

 shawnwall29 янв. 2011 г., 03:06
Спасибо Вам за информацию. Документы, с которыми я сейчас работаю, относятся к / A и Goto. Сейчас я нахожусь в точке, где я могу создать заголовок страниц в оглавлении. Я вижу словари страниц / A / D / 0 в Схемах и соответствующие им словари страниц / A / D / 0 на страницах. Я пытаюсь создать словарь заголовка-> страницы nvp, но я не могу добавить CGPDFDictionaryRef в NSDictionary ...
 shawnwall29 янв. 2011 г., 04:41
Я закончил проверку на равенство, сравнив строковое значение потоков содержимого словарей toc-страниц и фактических словарей pageref на странице ... не кажется чистым, но работает. Есть ли способ лучше?
 Joey10 февр. 2011 г., 10:25
как получить строковое значение потоков контента? не могли бы вы дать мне больше чаевых? В моем случае «/Outlines/.../A/D/0» работает нормально, но я не могу проверить равенство из «/Annots/.../A/D/0»
 omz11 февр. 2011 г., 16:31
@sw: это не сработает, если у вас две страницы с одинаковым содержанием (редко, но возможно). Это также довольно медленно делать все сравнения строк. Почему бы просто не использовать пользовательский класс модели, который хранит заголовок и CGPDFDictionary в качестве переменной экземпляра?

Ваш ответ на вопрос