Непрозрачность iText Background - PullRequest
0 голосов
/ 05 марта 2019

Я хочу наложить текст с полупрозрачным фоном поверх существующего текста с помощью iText 7. Настройка непрозрачности фона для элемента text не работает (строка 1), я могу установить его только дляцелое paragraph (строка 2):

enter image description here

import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import java.io.IOException;

public class TextBackgroundOpacityTest {

    public static void main(String[] args) throws IOException {

        try (Document doc = new Document( new PdfDocument(new PdfWriter("TextBackgroundOpacityTest.pdf")))) {
            doc.add(new Paragraph(new String(new char[130]).replace("\0", "A")));

            // opacity doesn't work for text element
            doc.showTextAligned(new Paragraph(new Text("missing background transparency").setBackgroundColor(ColorConstants.WHITE, .8f)), 500, 805, 0, TextAlignment.RIGHT, VerticalAlignment.TOP, 0);

            // opacity for the whole paragraph works, but this is not what I want
            doc.showTextAligned(new Paragraph("whole pharagraph background transparancy").setBackgroundColor(ColorConstants.WHITE, .8f), 500, 785, 0, TextAlignment.RIGHT, VerticalAlignment.TOP, 0);
        }
    }    
}

Как мне наложить текст на полупрозрачный фон, как показано в строке 2, но только для наложенного текста, а не весь абзац?Желаемый выход: enter image description here

1 Ответ

0 голосов
/ 06 марта 2019

Чтобы обойти решение, вы можете использовать пользовательские средства визуализации. Если вы посмотрите на BlockRenderer#drawBackground, который вызывается, если вы устанавливаете прозрачный фон для абзаца, вы можете увидеть следующие строки:

TransparentColor backgroundColor = new TransparentColor(background.getColor(), background.getOpacity());
drawContext.getCanvas().saveState().setFillColor(backgroundColor.getColor());
backgroundColor.applyFillTransparency(drawContext.getCanvas());

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

TransparentColor backgroundColor = new TransparentColor(background.getColor(), background.getOpacity());
backgroundColor.applyFillTransparency(drawContext.getCanvas());

В целом получаем следующую реализацию:

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

    @Override
    public void drawBackground(DrawContext drawContext) {
        Background background = this.<Background>getProperty(Property.BACKGROUND);
        Float textRise = this.getPropertyAsFloat(Property.TEXT_RISE);
        Rectangle bBox = getOccupiedAreaBBox();
        Rectangle backgroundArea = applyMargins(bBox, false);
        float bottomBBoxY = backgroundArea.getY();
        float leftBBoxX = backgroundArea.getX();
        if (background != null) {
            boolean isTagged = drawContext.isTaggingEnabled();
            PdfCanvas canvas = drawContext.getCanvas();
            if (isTagged) {
                canvas.openTag(new CanvasArtifact());
            }
            boolean backgroundAreaIsClipped = clipBackgroundArea(drawContext, backgroundArea);

            canvas.saveState().setFillColor(background.getColor());
            TransparentColor backgroundColor = new TransparentColor(background.getColor(), background.getOpacity());
            backgroundColor.applyFillTransparency(drawContext.getCanvas());

            canvas.rectangle(leftBBoxX - background.getExtraLeft(), bottomBBoxY + (float) textRise - background.getExtraBottom(),
                    backgroundArea.getWidth() + background.getExtraLeft() + background.getExtraRight(),
                    backgroundArea.getHeight() - (float) textRise + background.getExtraTop() + background.getExtraBottom());
            canvas.fill().restoreState();
            if (backgroundAreaIsClipped) {
                drawContext.getCanvas().restoreState();
            }
            if (isTagged) {
                canvas.closeTag();
            }
        }
    }

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

Чтобы элемент Text использовал пользовательскую реализацию средства визуализации, просто вызовите метод setNextRenderer:

Text customTextElement = new Text("missing background transparency");
customTextElement.setNextRenderer(new TextRendererWithBackgroundOpacity(customTextElement));

Кстати, вы можете подать исправление как запрос на извлечение к iText (хотя, пожалуйста, следуйте рекомендациям по внесению изменений ). Хранилище находится по адресу https://github.com/itext/itext7

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