iText背景不透明度

问题描述 投票:0回答:1

我想使用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

opacity itext7
1个回答
1
投票

要解决该解决方案,您可以使用自定义渲染器。如果您查看调用的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(尽管请遵循contribution guidelines)。存储库位于https://github.com/itext/itext7

© www.soinside.com 2019 - 2024. All rights reserved.