Текстовый элемент с графическими текстовыми эффектами - PullRequest
0 голосов
/ 07 апреля 2020

Я хочу создать Text элементов (com.itextpdf.layout.element.Text) с различными дополнительными графическими эффектами, например, тенью или добавлением некоторой текстуры на глифы. (см. DropShadow некоторый 3D-эффект ) Каков наилучший способ достижения этого?

Лучшая идея, которую я до сих пор имел, - это использовать режим обрезки текста. (Определено в PDF 32000-1 9.3.6; com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants.TextRenderingMode). Рисование текста как границы отсечения и применение некоторой текстуры или рисование дополнительного теневого «слоя». Однако обтравочный контур восстанавливается до состояния перед отрисовкой текста с canvas.restoreState(), который вызывается в конце в com.itextpdf.layout.renderer.TextRender#draw. Расширение этого на пользовательский TextRenderer может работать, но функция рисования является большой с некоторыми вызовами к частным функциям TextRenderer.

Есть какие-нибудь ссылки для других возможных методов?

1 Ответ

0 голосов
/ 07 апреля 2020

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

Другая идея - подключить к PdfCanvas, который выполняет низкоуровневое рисование. Вы можете создать свою собственную оболочку, подобную следующей, и делегировать все операции экземпляру PdfCanvas, который вы оберните, за исключением пары «интересных» операций, в которых вы будете настраивать logi c и применять некоторые стили:

private static class PdfCanvasWrapper extends PdfCanvas {
    private PdfCanvas delegate;
    public PdfCanvasWrapper(PdfCanvas wrapped) {
        super(wrapped.getContentStream(), wrapped.getResources(), wrapped.getDocument());
        this.delegate = wrapped;
    }

    // "Interesting" methods
    @Override
    public PdfCanvas endText() {
        delegate.endText();
        delegate.setFillColor(ColorConstants.BLACK);
        delegate.rectangle(10, 10, 300, 300);
        delegate.fill();
        return this;
    }

    // "Boring" methods - just delegate the implementation to the wrapped instance
    @Override
    public PdfCanvas beginVariableText() {
        delegate.beginVariableText();
        return this;
    }

    @Override
    public PdfCanvas endVariableText() {
        delegate.endVariableText();
        return this;
    }

    // Override all other members like above
}

В этом случае ваш пользовательский текстовый рендерер подключит только правильный DrawContext, но будет использовать операцию draw по умолчанию:

private static class CustomTextRenderer extends TextRenderer {
    public CustomTextRenderer(Text textElement) {
        super(textElement);
    }

    @Override
    public void draw(DrawContext drawContext) {
        DrawContext newContext = new DrawContext(drawContext.getDocument(), new PdfCanvasWrapper(drawContext.getCanvas()));
        super.draw(newContext);
    }

    @Override
    public CustomTextRenderer getNextRenderer() {
        return new CustomTextRenderer((Text) modelElement);
    }
}

Main может выглядеть так:

Paragraph p = new Paragraph();
Text text = new Text("Hello");
text.setTextRenderingMode(TextRenderingMode.CLIP);
text.setNextRenderer(new CustomTextRenderer(text));
p.add(text);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...