PDFsharp DrawString Text对于某些PDF不可见

时间:2017-01-11 12:03:23

标签: c# pdf pdfsharp

我正在制作的系统用PDF标记某些信息。它通过在文档的右上角创建一个青柠绿色文本框来完成此操作。然后它在绿色空间的顶部绘制一个字符串。这适用于成千上万的PDF,但对于其中一个,即使绘制了框,文本也是不可见的。我仍然可以选择文本并将其复制到其他内容,但它在PDF中是不可见的。

不幸的是,我无法共享PDF,但它是PDF 1.4。会导致这种情况的原因是什么?

标记代码:

    private static XGraphics drawString(XGraphics xgr, PdfPage page, string printString, int pageNumber = 0)
    {
        XFont font = new XFont("Verdana", 10, XFontStyle.BoldItalic);

        var textSize = xgr.MeasureString(printString, font);
        var width = textSize.Width;
        var height = textSize.Height;

        double xMin = 0;
        double yMin = 0;

        if (page.Rotate == 90)
        {
            xMin = page.Height - textSize.Width;
            var state = xgr.Save();
            xgr.DrawRectangle(XBrushes.LimeGreen, xMin, yMin, width, height);
            xgr.Restore(state);
            xgr.DrawString(printString, font, XBrushes.Black, new XRect(0, 0, page.Height, page.Width), topRight()); 
        }
        else 
        {
            xMin = page.Width - textSize.Width;
            var state = xgr.Save();
            xgr.DrawRectangle(XBrushes.LimeGreen, xMin, yMin, width, height);
            xgr.Restore(state);
            xgr.DrawString(printString, font, XBrushes.Black, new XRect(0, 0, page.Width, page.Height), topRight()); 
        }

        return xgr;
    }

    private static XStringFormat topRight()
    {
        XStringFormat format = new XStringFormat();
        format.Alignment = XStringAlignment.Far;
        format.LineAlignment = XLineAlignment.Near;
        return format;
    }

我尝试在xgr上使用Dipose()并在每个绘制操作之前重新初始化它。我已经尝试在代码中看到的保存和恢复绘制操作之间的xgr状态。我尝试过各种各样的字体和字体,也没有运气。

让我知道有关PDF的元数据是相关的,我将与您分享。

5 个答案:

答案 0 :(得分:0)

下面是我用来隐藏文档中的内容并编辑文档并再次保存的代码。如果有帮助,请告诉我

private PdfDocument FormatPdfDocument(PdfDocument document, List<string> packingTypes, string carrierName)
{
    XFont PackingTypeFont = new XFont("Calibri", 10, XFontStyle.Bold);
    var i = 0;
    foreach (PdfPage page in document.Pages)
    {
        using (var gfx = XGraphics.FromPdfPage(page))
        {
            var packingType = packingTypes.ElementAtOrDefault(i++) ?? "PackingType Not Found";
            if (carrierName == "xxxx")
            {
                var packingTypeBounds = new XRect(64, 62, 200, 12);
                gfx.DrawRectangle(XBrushes.White, packingTypeBounds);
                gfx.DrawString(packingType, PackingTypeFont, XBrushes.Black, packingTypeBounds, XStringFormats.TopLeft);

                var logoBounds = new XRect(0, 0, 130, 50);
                gfx.DrawRectangle(XBrushes.White, logoBounds);
            }
            else if (carrierName == "yyyy")
            {
                var packingTypeBounds = new XRect(200, 0, 200, 12);
                gfx.DrawString(packingType, PackingTypeFont, XBrushes.Black, packingTypeBounds, XStringFormats.TopLeft);
            }
            else if (carrierName == "zzzz")
            {
                var packingTypeBounds = new XRect(410, 20, 200, 12);
                var state = gfx.Save();
                gfx.RotateAtTransform(90, new XPoint { X = 410, Y = 20 });
                gfx.DrawString(packingType, PackingTypeFont, XBrushes.Black, packingTypeBounds, XStringFormats.TopLeft);
                gfx.Restore(state);
            }
        }
    }    
    return document;
}

这对我来说没问题,直到日期没有任何问题

答案 1 :(得分:0)

回答您问题的一些可能原因&#34;会导致这种情况的原因是什么?&#34;:

您使用的是最新版本的PDFsharp 1.50 beta 3b吗? IIRC 1.32中存在一个可能导致意外行为的错误,因为某些属性未被重置 由于您看到矩形,这可能是原因。

由于您看到矩形,这可能不适用:
有两种方法可以修改现有页面:&#34;追加&#34;和&#34; prepend&#34;。您的代码段未显示您是如何执行此操作的。 使用&#34; prepend&#34;您的石灰矩形可以隐藏在白色填充的矩形下。使用活动的透明网格在Adobe Reader中观看PDF,并检查您是否看到矩形所在的网格。

由于您看到矩形,这可能不适用:
也许你的文字走错了位置。检查要修改的PDF页面的MediaBox和CropBox设置。通常页面从(0,0)开始,但你不能确定 在PDF文件中找到您的文本,并将文本位置与MediaBox和CropBox进行比较。

这可能是PDFsharp中的未知错误。如果您没有找到允许复制您可以共享的问题的PDF,那么修复该错误将非常困难。但也许上述选项之一可以带来成功。

答案 2 :(得分:0)

所以我设法找到一种方法让它发挥作用。我在文档上运行了两次冲压过程,它按预期工作。幸运的是,加盖两次不会影响实际正常工作的常规文件。

答案 3 :(得分:0)

使用PdfSharp 1.5 GDI,我也遇到过这个问题。有些pdf会没问题,有些可能有1或2页可以正常,然后其他人没有正常的页面。可以选择文本,但无法看到文本。更改renderMode可以解决问题。

在PdfGraphicsState.cs中,有一个条件来检查_realizedRenderingMode!= renderMode。但是,_realizedRenderingMode和renderMode默认为0,因此它永远不会进入代码块,也不会有更改renderMode的方法,除非您将字体更改为斜体,粗体,删除线或下划线:

    int _realizedRenderingMode;  // Reference: TABLE 5.2  Text state operators / Page 398

    public void RealizeFont(XFont font, XBrush brush, int renderingMode)
    {
        const string format = Config.SignificantFigures3;

        // So far rendering mode 0 (fill text) and 2 (fill, then stroke text) only.
        RealizeBrush(brush, _renderer._colorMode, renderingMode, font.Size); // _renderer.page.document.Options.ColorMode);

        // Realize rendering mode.
        if (_realizedRenderingMode != renderingMode)
        {
            _renderer.AppendFormatInt("{0} Tr\n", renderingMode);
            _realizedRenderingMode = renderingMode;
        }

删除条件就足以解决问题,但在XGraphicsPdfRenderer.cs中,对于BT(开始文本),renderMode似乎只需要一次。

    internal void BeginTextMode()
    {
        if (_streamMode != StreamMode.Text)
        {
            _streamMode = StreamMode.Text;
            _content.Append("BT\n");
            // Text matrix is empty after BT
            _gfxState.RealizedTextPosition = new XPoint();
            _gfxState.ItalicSimulationOn = false;
        }
    }

所以,我最终修改了XGraphics以包含XGraphicsPdfRendererOptions并将变量传递给各种方法,因此无论位置如何都可以更改它:

    private XGraphicsPdfRendererOptions _renderOptions { get; set; }
    public XGraphicsPdfRendererOptions RenderOptions
    {
        get
        {
            if (_renderOptions == null)
            {
                _renderOptions = new XGraphicsPdfRendererOptions();
            }

            return _renderOptions;
        }
        set
        {
            _renderOptions = value;
        }
    }

请记住,renderMode最初是基于字体是斜体,粗体,删除线还是下划线,我在XGraphicsPdfRenderer.cs中没有真正看到它们与renderMode的关系:

            //bool bold = (font.Style & XFontStyle.Bold) != 0;
        //bool italic = (font.Style & XFontStyle.Italic) != 0;
        bool italicSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.ItalicSimulation) != 0;
        bool boldSimulation = (font.GlyphTypeface.StyleSimulations & XStyleSimulations.BoldSimulation) != 0;
        bool strikeout = (font.Style & XFontStyle.Strikeout) != 0;
        bool underline = (font.Style & XFontStyle.Underline) != 0;

        Realize(font, brush, boldSimulation ? 2 : 0);

Class and enum:

public class XGraphicsPdfRendererOptions
{
    public XGraphicsPdfRenderMode RenderMode { get; set; }
    public bool IncludeRenderModeForPage { get; set; }
    public bool IncludeRenderModeForObject { get; set; }
}

public enum XGraphicsPdfRenderMode
{
    Text_Render_Mode_Fill = 0,
    Text_Render_Mode_Stroke = 1,
    Text_Render_Mode_Fill_Stroke = 2,
    Text_Render_Mode_Invisible = 3
}

用法:

gfx.RenderOptions = new XGraphicsPdfRendererOptions() { RenderMode = XGraphicsPdfRenderMode.Text_Render_Mode_Fill, IncludeRenderModeForPage = true };

https://github.com/zaryk/PDFsharp

答案 4 :(得分:0)

我已经在这个问题上发生了几次,现在在不同的项目上。我发现最简单的解决方法是处置XGraphics对象,然后使用当前的PdfPage实例重新实例化它。

 PdfSharp.Pdf.PdfPage Page = Document.AddPage();

 PdfSharp.Drawing.XGraphics gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(Page);

 //Build your pdf here until transparency issue occurs

 //Issue has occured so re-instantiate gfx object
 gfx.Dispose();
 gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(Page);

 //Continue as normal