2016-05-18 4 views
4

Это связано с предыдущим вопросом, который я задал о reading an annotation's appearance stream and writing its text to the Contents. Я хотел бы сделать аналогичное действие с аннотацией Line, прочитав его ширину внешнего вида и установив фактическую ширину в соответствии с внешним видом.Как читать ширину внешнего вида строки, используя iTextSharp?

У меня возникли проблемы с тем, как настроить функцию «set text contents using appearance» для установки ширины линии. Это код, который я сейчас использую для получения текста:

//main function for setting inner content to appearance value 
public void changeAnnotationContentToAppearance(PdfDictionary dict) 
     { 

       string surface = pdfTextParser.retrieveText(dict); 
       if (surface != null) 
       { 
        //update CONTENTS with appearance 
        //for changing line width, I would instead modify the /BS dictionary's /W key value, i think 
        dict.Put(PdfName.CONTENTS, new PdfString(surface)); 
       } 
     } 

//get text from /AP dictionary 
public string retrieveText(PdfDictionary annotDictionary) 
    { 

     PdfDictionary appearancesDictionary = annotDictionary.GetAsDict(PdfName.AP); 
     foreach (PdfName key in appearancesDictionary.Keys) 
     { 
      PdfStream value = appearancesDictionary.GetAsStream(key); 
      if (value != null) 
      { 
       String text = ExtractAnnotationText(value); 
       return text; 
      } 
     } 
     return null; 

    } 

//read the appearance stream and extract text contents 
public String ExtractAnnotationText(PdfStream xObject) 
{ 
    PdfDictionary resources = xObject.GetAsDict(PdfName.RESOURCES); 
    ITextExtractionStrategy strategy = new LocationTextExtractionStrategy(); 

    PdfContentStreamProcessor processor = new PdfContentStreamProcessor(strategy); 
    processor.ProcessContent(ContentByteUtils.GetContentBytesFromContentObject(xObject), resources); 
    return strategy.GetResultantText(); 
} 

ExtractAnnotationText() только кажется способным читать текст, а не ширина линии, потому что ITextExtractionStrategy() не имеет методы для возврата свойств линии. Предлагает ли iTextSharp другую стратегию добычи для использования при работе с линиями?

Если я читаю право, this question, this one и this one предположить, что я должен был бы реализовать класс, но я не уверен, какой из них я должен подклассы для получения данных строки, или как именно я бы идти о делая это.

EDIT: Я также хотел бы получить данные о внешнем виде для точек, определяющих прямоугольник в текстовом поле. Хотя это может быть другой вопрос, похоже, это связано с этой проблемой: получение нетекстовых графических данных, определяющих поток внешнего вида аннотации.

ответ

2

Для получения информации о строках и фигурах вам понадобится объект PathRenderInfo. Объект PathRenderInfo был введен в IText 7. Это доказательство концепции я очень быстро написал:

public static void main(String args[]) throws IOException { 
    PdfDocument document = new PdfDocument(new PdfReader(SRC)); 
    PdfPage page = document.getPage(1); 
    PdfCanvasProcessor processor = new PdfCanvasProcessor(new IEventListener() { 
     public void eventOccurred(IEventData data, EventType type) { 
      if (type == EventType.RENDER_PATH) { 
       PathRenderInfo renderinfo = (PathRenderInfo) data; 
       int i = renderinfo.getOperation(); 
       switch (i) { 
        case 1: 
         System.out.print("Stroke: "); 
         break; 
        case 2: 
         System.out.print("Fill: "); 
         break; 
        default: 
         System.out.print("No: "); 
       } 
       for (Subpath p : renderinfo.getPath().getSubpaths()) { 
        for (IShape shape : p.getSegments()) { 
         for (Point point : shape.getBasePoints()) { 
          System.out.println(String.format("x = %s; y = %s", point.getX(), point.getY())); 
         } 
        } 
       } 
      } 
     } 
     public Set<EventType> getSupportedEvents() { 
      return null; 
     } 
    }); 
    processor.processPageContent(page); 
} 

Я побежал на PDF с большим количеством строк, и это было (часть) выход:

Stroke: x = -406.0; y = -240.0 
x = 406.0; y = -240.0 
x = -406.0; y = -200.0 
x = 406.0; y = -200.0 
x = -406.0; y = -160.0 
x = 406.0; y = -160.0 
x = -406.0; y = -120.0 
x = 406.0; y = -120.0 
x = -406.0; y = -80.0 
x = 406.0; y = -80.0 
x = -406.0; y = -40.0 
x = 406.0; y = -40.0 
x = -406.0; y = 0.0 
x = 406.0; y = 0.0 
x = -406.0; y = 40.0 
x = 406.0; y = 40.0 
x = -406.0; y = 80.0 

Вам необходимо перейти на iText 7, чтобы выполнить эту работу, и вам также нужно будет изучить, какая информация содержится в объектах PathRenderInfo, Subpath и IShape.

Update:

Как указано в комментариях, можно было бы интересно, если вы задаете правильный вопрос. Посмотрите на этот снимок экрана:

enter image description here

Если заглянуть внутрь этого PDF, вы не найдете поток внешний вид:

enter image description here

Появление создается зрителем на основе от значений, таких как:

  • /C: цвет: красный = 0, зеленый = 0, синий = 1 (следовательно, линия синего цвета)
  • /LE: линия окончаний (в данном случае: алмаз форма)
  • L: грань между (х = 20, у = 790) и (х = 575, у = 790)
  • ...

Зачем вам разбирать внешний вид, если у вас есть вся необходимая информация в словаре аннотаций?

То же самое касается прямоугольника текстовой аннотации. Эта информация хранится в значении /Rect. В этом случае аннотация безразмерна ([0 0 0 0]), потому что мы имеем только одно измерение, а строка определяется значениями, хранящимися в /L.

+0

Доступен ли 'PathRenderInfo' под другим именем в iTextSharp (мой проект находится на C#)? Кроме того, знаете ли вы, работает ли этот подход для аннотаций строк и аннотаций? Или просто фигуры? – sigil

+1

iText 7 для C# выйдет в июне. Функциональность работает для потоков контента (например, поток содержимого страницы, поток внешнего вида аннотации, ...). Обратите внимание, что аннотации не требуют потока появления. Если вы посмотрите на словарь аннотаций, вы найдете пограничные словари, координаты аннотаций строк и т. Д. Однако в вашем вопросе вы явно попросили способ разобрать поток внешнего вида. –

+1

Я обновил свой ответ, если ваш вопрос был неправильным. –

2

ОП разъяснено в комментарии к @ ответу Бруно

Я хочу, чтобы разобрать поток внешнего вида и использовать его значение для установки значений в словаре аннотаций.

и

, когда поток внешнего вида не соответствует этим значениям (например, граница черного цвета в словаре, но красная в потоке внешнего вида), ... Я хочу, чтобы установить словарь контенты поток появления. Эта проблема возникает в некоторых файлах PDF, которые создаются в Foxit, а затем открываются в Adobe.

К сожалению, PDF позволяет создавать множество подобных эффектов. Для того, чтобы нарисовать границу, например,

  • вы можете ударить по пути из четырех линий,
  • или вы можете ударить прямоугольник,
  • или вы можете заполнить прямоугольник и заполнить еще один, немного меньший внутренний прямоугольник белый,
  • или вы можете заполнить все с прямоугольной маской,
  • или вы можете нарисовать битмап с желаемой формой,
  • или вы можете ...
  • ...

Таким образом, действительно универсальное решение для вашей проблемы находится где-то между чрезвычайно сложными и невозможными.

Кроме того, некоторые представления могут быть невозможны для представления, используя только ограниченные абстрактные настройки в словаре аннотаций. Например. граница в потоке внешнего вида может быть создана сплошной в середине, но исчезает слева и справа с использованием прозрачности или может быть нарисована с использованием оператора цветового затенения, приводящего к цветовому градиенту, или его форма может быть не совсем прямоугольной, а вместо нерегулярной, или, или ...


Если вы не ищете общее решение, хотя, но только для решения рабочих для аннотаций, созданных определенных программных продуктов, таких как Foxit в некоторых версиях, и если внешность создана этим программным обеспечением может быть представлено с использованием значений словарного аннотационного словаря, задача становится выполнимой.

В этом случае вы должны начать с анализа потоков внешнего вида, созданных этими программными продуктами. Скорее всего, появится какая-то модель.

Как только вы нашли этот шаблон, вы можете начать реализацию соответствующего iTextSharp 5.5.x IExtRenderListener или iTextSharp 7.0.x IEventListener.

+0

В [этом ответе] (http://stackoverflow.com/a/37022267/619177) вы предоставили образец данных потока внешнего вида. Как вы это узнали? Я не смог найти, где находится объект 'PdfStream'. – sigil

+1

См. [GetN2fromSig] (http://developers.itextpdf.com/examples/security/inspect-digital-signatures#1346-getn2fromsig.java) –

+1

Ссылка @sigil Bruno показывает, как можно прочитать содержимое потока в собственном код. Чтобы получить поток в ответе, на который вы указываете, я использовал [RUPS] (http://itextpdf.com/Products/itext-rups) инструмент на основе iText. – mkl