Внешний вид аннотации Box Cloud в iText

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

вы можете найти класс границы здесь.

Моя проблема в том, что верхние и правые граничные облака не рисуются. кажется, что их расположение нарисовано за пределами прямой разницы. Я полагаю, что проблема заключается в рисовании кривых в cloudyPolygonImpl(). может быть, у itext есть разные способы рисования в PdfAppearance? Я не уверена.

Это то, что у меня есть до сих пор. Внешний вид аннотации Box Cloud в iText

    public class Test {
    public static void main(String[] args) throws Exception {
    PdfReader reader = new PdfReader("src.pdf");
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("result.pdf"));

    PdfDictionary be = new PdfDictionary();
    be.put(PdfName.S, PdfName.C);
    be.put(PdfName.I, new PdfNumber(1));

    Rectangle location = new Rectangle(123.6f, 584.4f, 252.6f, 653.4f);
    PdfAnnotation stamp = PdfAnnotation.createSquareCircle(stamper.getWriter(), location, "", true);
    stamp.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
    stamp.put(new PdfName("BE"), be);
    stamp.setColor(BaseColor.RED);

    PdfContentByte cb = stamper.getOverContent(1);
    PdfAppearance app = cb.createAppearance(location.getWidth(), location.getHeight());
    stamp.setAppearance(PdfName.N, app);

    PdfArray stickyRect = stamp.getAsArray(PdfName.RECT);
    Rectangle annotRect = new Rectangle(stickyRect.getAsNumber(0).floatValue(),
        stickyRect.getAsNumber(1).floatValue(),
        stickyRect.getAsNumber(2).floatValue(),
        stickyRect.getAsNumber(3).floatValue());

    PdfArray arrDiff = annotation.getAsArray(PdfName.RD);
    Rectangle annotRectDiff = null;
    if (arrDiff != null) {
            annotRectDiff = new Rectangle(arrDiff.getAsNumber(0).floatValue(), arrDiff.getAsNumber(1).floatValue(),
        arrDiff.getAsNumber(2).floatValue(), arrDiff.getAsNumber(3).floatValue()
    }

    // Create cloud appearance
    CBorder cborder = new CBorder(app, 1, 1, annotRect);
    cborder.createCloudyRectangle(annotRectDiff);

    stamp.put(PdfName.RECT, new PdfRectangle(cborder.getRectangle()));
    stamp.put(PdfName.RD, new PdfArray(new float[] { 
        cborder.getRectDifference().getLeft(), 
        cborder.getRectDifference().getBottom(), 
        cborder.getRectDifference().getRight(), 
        cborder.getRectDifference().getTop() }));

    app.rectangle(cborder.getBBox());
    app.transform(cborder.getMatrix());


    app.setColorStroke(BaseColor.RED);
    app.setLineWidth(1);
    app.stroke();

    stamper.addAnnotation(stamp, 1);
    stamper.close();
    reader.close();
}    
    }

Правильный вывод должен заключаться в том, что все границы рисуются облаком, но в настоящее время рисуются только левая и нижняя.

Вы вызвали cborder.createCloudyRectangle(null);, а PDFBox PDSquareAppearanceHandler.java вызвал cloudyBorder.createCloudyRectangle(annotation.getRectDiffere‌​nce());. PDFBox также изменяет прямоугольник аннотаций после того, как облака будут готовы. (Adobe Reader также делает это IIRC)

Tilman Hausherr 03.06.2019 10:45

Привет, тильман. да. экспериментировал с кодом, но результат тот же, поскольку getRectDifference() возвращает null даже в pdfbox, и даже когда я использовал этот метод вместо null, результат был таким же. я верну код обратно.

chitgoks 04.06.2019 01:59

@TilmanHausherr значения прямоугольника такие же, как значения в PDFBox. Я полагаю, что проблема может быть в cloudyPolygonImpl() граничного класса. в iText он может отличаться в зависимости от того, как он нарисован.

chitgoks 04.06.2019 04:20

Ваше недавнее редактирование странное, оно вводит новую переменную annotation, которая нигде не определена, а код в новом блоке if (arrDiff != null) синтаксически нарушен. Таким образом, я отвечу на основе исходного кода.

mkl 04.06.2019 12:04

Кстати: у вашего кода есть проблемы с поворотом страницы на 90° или 270°...

mkl 04.06.2019 12:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
649
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

(Этот ответ основан на коде в 3 версия вашего вопроса, поскольку изменения в ревизия 4 привели к множеству ошибок.)

Ваш код здесь создает недопустимый поток внешнего вида аннотации:

CBorder cborder = new CBorder(app, 1, 1, annotRect);
cborder.createCloudyRectangle(null);

stamp.put(PdfName.RECT, new PdfRectangle(cborder.getRectangle()));
stamp.put(PdfName.RD, new PdfArray(new float[] { 
    cborder.getRectDifference().getLeft(), 
    cborder.getRectDifference().getBottom(), 
    cborder.getRectDifference().getRight(), 
    cborder.getRectDifference().getTop() }));

app.rectangle(cborder.getBBox());
app.transform(cborder.getMatrix());


app.setColorStroke(BaseColor.RED);
app.setLineWidth(1);
app.stroke();

Его верхняя часть создает путь:

2 j
121.58 588.63 m
122.06 588.95 122.6 589.18 123.16 589.3 c
120.73 588.78 119.18 586.4 119.7 583.96 c
120.19 581.67 122.35 580.14 124.68 580.44 c
...
122.06 596.42 122.6 596.64 123.16 596.76 c
121.09 596.32 119.6 594.49 119.6 592.36 c
119.6 590.87 120.34 589.47 121.58 588.63 c
h

Тогда app.rectangle(cborder.getBBox()) ничего не создает (остерегайтесь, эта rectangle перегрузка делает не то, что вы ожидаете!).

Затем app.transform(cborder.getMatrix()) добавляет изменение в текущую матрицу преобразования, app.setColorStroke(BaseColor.RED) добавляет изменение цвета обводки и app.setLineWidth(1) добавляет изменение ширины линии:

1 0 0 1 -118.68 -579.48 cm
1 0 0 RG
1 w

И, наконец, app.stroke() добавляет команду для обводки пути:

S

Но между определением пути и соответствующей командой рисования пути разрешены только инструкции отсечения пути! См. Рисунок 9 – Графические объекты – в спецификации PDF ISO 32000-1.

Вы можете исправить этот код следующим образом, подтягивая изменения цвета и ширины линии и напрямую используя ограничивающую рамку облака:

// Create cloud appearance
app.setColorStroke(BaseColor.RED);
app.setLineWidth(1);

CBorder cborder = new CBorder(app, 1, 1, annotRect);
cborder.createCloudyRectangle(null);

stamp.put(PdfName.RECT, new PdfRectangle(cborder.getRectangle()));
stamp.put(PdfName.RD, new PdfArray(new float[] { 
    cborder.getRectDifference().getLeft(), 
    cborder.getRectDifference().getBottom(), 
    cborder.getRectDifference().getRight(), 
    cborder.getRectDifference().getTop() }));

app.stroke();
app.setBoundingBox(cborder.getBBox());

(тест CloudBoxАннотацияtestDrawLikeChitgoksImproved)

Это, в частности, изменяет результат (как показано в Adobe Acrobat) с

Screenshot original

к

Screenshot fix

оно работает! Хотя я думал, что сделать это так же, как PDFBox, поможет. Меня удивило отсутствие необходимости использовать cs.rectangle() и cs.transform(). Тот же самый способ, которым вы делали это, чтобы нарисовать аннотацию облака, также работает. Спасибо!

chitgoks 04.06.2019 15:08

@chitgoks хорошо, ваш первоначальный подход пытался переместить внешний вид в соответствии с ранее установленным значением границы внешнего вида аннотации. Мой подход изменил значение граничной рамки внешнего вида аннотации, чтобы оно соответствовало недвижимому внешнему виду. Любой подход может работать.

mkl 04.06.2019 16:20

Другие вопросы по теме