在PDF中搜索带下划线和粗体文字

时间:2018-03-29 20:06:26

标签: c# pdf search itext

使用iTextSharp,我如何确定解析后的文本块是否加粗和加下划线?

详细说明:
我正在尝试用C#解析.PDF文件,专门用于粗体和下划线的文本。使用ITextSharp,我可以从LocationTextExtractionStrategy派生,并从传递给重写的.RenderText方法的iTextSharp.text.pdf.parser.TextRenderInfo对象中获取文本,位置,字体等。
但是,确定TextRenderInfo对象中的文本是否为粗体和/下划线并不是直截了当的。

  • 我尝试使用TextRenderInfo.GetFont()查找字体属性,但未成功
  • 我目前可以通过访问TextRenderInfo对象上的私有Graphics State字段并检查它的.Font.PostscriptFontName属性来确定单词“Bold”(丑陋,但似乎有效),从而确定文本是否为Bold。 / LI>
  • 最大的问题:我没有找到任何东西来确定文本是否加下划线。我怎样才能确定这个?

这是我目前的尝试:

        private FieldInfo _gsField = typeof(TextRenderInfo).GetField("gs",
        BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);

        //Automatically called for each chunk of text in the PDF
        public override void RenderText(TextRenderInfo renderInfo)
        {
            base.RenderText(renderInfo);
            //UNDONE:Need to determine if text is underlined.  How?

            //NOTE: renderInfo.GetFont().FontWeight does not contain any actual information
            var gs = (GraphicsState)_gsField.GetValue(renderInfo);
            var textChunkInfo = new TextChunkInfo(renderInfo);
            _allLocations.Add(textChunkInfo);
            if (gs.Font.PostscriptFontName.Contains("Bold"))
                //Add this to our found collection
                FoundItems.Add(new TextChunkInfo(renderInfo));

            if (!_lineHeights.Contains(textChunkInfo.LineHeight))
                _lineHeights.Add(textChunkInfo.LineHeight);
        }

当前尝试的完整源代码:GitHub Repository(两个示例(example.pdfexample2.pdf)包含在与我将要搜索的文本类似的文本中。)

1 个答案:

答案 0 :(得分:2)

  
      
  • 我尝试使用TextRenderInfo.GetFont()查找字体属性,但未成功

  •   
  • 我目前可以通过访问TextRenderInfo对象上的私有Graphics State字段并检查它的.Font.PostscriptFontName属性来确定单词“Bold”(丑陋,但看起来有效),从而确定文本是否为Bold。 。)

  •   

我不太明白这种区别。 TextRenderInfo.GetFont()Font的私有图形状态字段的TextRenderInfo属性完全相同。

尽管如此,这确实是确定大胆的主要方法之一。

使用

大胆 以PDF格式撰写

  • 明确加粗字体(这是更好的方式);在这种情况下,可以尝试通过

    确定字体是否为粗体
    • 查看字体名称:它可能包含子字符串“bold”或类似名称;

    • 查看字体的一些可选属性,例如字体粗细,但要注意,它们是可选的......

    • 检查嵌入的字体文件(如果适用)。

    这些方法都不是万无一失的;

  • 与非粗体文本相同的字体,但使用特殊技术使它们显示为粗体(又名穷人的粗体),例如。

    • 不仅可以填充字形轮廓,还可以沿着它绘制更粗的线条,以获得大胆的印象,

    • 两次绘制字形,第二次略微移位,也是一种大胆的印象。

带下划线 写入PDF通常是通过在文本下明确绘制线条或非常细的矩形来实现的。您可以通过实现IExtRenderListener来尝试检测此类行,使用它解析相关页面以确定行位置,然后在文本提取期间与文本位置匹配。两者都可以在一次通过中完成,但要注意,不需要在文本之前绘制下划线,或者甚至不久之后,pdf生成器可以首先绘制所有文本,然后才绘制所有下划线。此外,我也遇到了一个有趣的结构,非常短(例如1pt)非常宽(例如50pt)的垂直线有效地被看作是水平的......

IExtRenderListener使用三种新方法[{1}},IRenderListenerModifyPath扩展了RenderPath。无论何时绘制某条路径,无论是单行,矩形还是某些非常复杂的路径,您都会首先获得一些ClipPath个调用(至少一个)

ModifyPath

定义路径所包含的行和曲线,然后最多一次/** * Called when the current path is being modified. E.g. new segment is being added, * new subpath is being started etc. * * @param renderInfo Contains information about the path segment being added to the current path. */ void ModifyPath(PathConstructionRenderInfo renderInfo); 调用

ClipPath

(当且仅当路径将作为以下绘图操作的剪辑路径时),最后只有一个/** * Called when the current path should be set as a new clipping path. * * @param rule Either {@link PathPaintingRenderInfo#EVEN_ODD_RULE} or {@link PathPaintingRenderInfo#NONZERO_WINDING_RULE} */ void ClipPath(int rule); 调用

RenderPath

定义如何绘制路径(填充其内部和抚摸路径本身的任何组合)。

即。要识别下划线,您必须收集通过/** * Called when the current path should be rendered. * * @param renderInfo Contains information about the current path which should be rendered. * @return The path which can be used as a new clipping path. */ Path RenderPath(PathPaintingRenderInfo renderInfo); 提供的路径片段,并在ModifyPath来电后立即决定是否可以描述一个或多个下划线。

理论上的下划线也可以不同的方式创建,例如:使用位图图像,但我不知道pdf生产者这样做。

顺便说一句,在您的示例中,PDF下划线始终显示为使用RenderPath到行起点,MoveTo到结尾,然后LineTo到简单地绘制抚摸路径。因此,您将分别获得两个Stroke个调用(一个具有操作值ModifyPath,一个具有MOVETO)和一个LINETO调用(具有操作RenderPath)每个下划线。