代码之家  ›  专栏  ›  技术社区  ›  Stef

iText背景不透明度

  •  0
  • Stef  · 技术社区  · 5 年前

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

    0 回复  |  直到 5 年前
        1
  •  1
  •   Alexey Subach    5 年前

    要解决此问题,可以使用自定义渲染器。如果你看看 BlockRenderer#drawBackground 如果将透明背景设置为段落,则调用此函数,您可以在其中看到以下行:

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

    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