我正在尝试使用PdfTron软件创建PDF编辑原型。
我已成功创建界面,用户可以点击图片,从PDF创建,选择区域,然后会显示一个文本输入,然后他/她可以输入文本,这将取代PDF文件中的内容。
现在文本替换部分存在问题。由于没有适用于Python的API文档(仅示例),因此我遵循Java / Android API文档。
我现在在哪里。我有以下代码来找出用户选择的矩形中的元素。值x1
,y1
,x2
,y2
是基于前端用户选择的PDF坐标。
rect = Rect(x1, y1, x2, y2)
text = ''
extractor = TextExtractor()
extractor.Begin(page)
line = extractor.GetFirstLine()
words = []
while line.IsValid():
word = line.GetFirstWord()
while word.IsValid():
elRect = word.GetBBox()
elRect.Normalize()
if elRect.IntersectRect(elRect, rect):
text += ' ' + word.GetString()
words.append(word)
word = word.GetNextWord()
line = line.GetNextLine()
words
基本上是我存储以后需要替换为新元素的内容的数组。
现在问题。我希望新元素具有与旧文本相同的样式和字体。 Api(link)告诉我使用
style = words[0].GetStyle()
给了我这个单词的风格,我可以使用
从样式中获取字体font = style.GetFont()
doc:https://www.pdftron.com/pdfnet/mobile/docs/Android/pdftron/PDF/TextExtractor.Style.html
但此返回的font
属于Obj
类而不是Font
类。
显然,使用字体创建新的文本元素需要Font
类的对象。
由于
element = eb.CreateTextBegin(font, 10.0);
生成错误:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/alan/.virtualenvs/pdfprint/local/lib/python2.7/site-packages/PDFNetPython2.py", line 5056, in CreateTextBegin
def CreateTextBegin(self, *args): return _PDFNetPython2.ElementBuilder_CreateTextBegin(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'ElementBuilder_CreateTextBegin'.
Possible C/C++ prototypes are:
pdftron::PDF::ElementBuilder::CreateTextBegin(pdftron::PDF::Font,double)
pdftron::PDF::ElementBuilder::CreateTextBegin()
也许有更好的方法来实现相同的结果?
EDIT1
阅读文档我发现您可以根据Font
创建Object
对象,如:
font = Font(style.GetFont())
仍然坚持使用这些风格创建元素。
/ EDIT1
EDIT2
我使用以下代码来测试写入文件:
style = elements[0].GetStyle()
font = Font(style.GetFont())
fontsize = style.GetFontSize()
eb = ElementBuilder()
element = eb.CreateTextBegin(font, 10.0)
writer.WriteElement(element)
element = eb.CreateTextRun('My Name')
element.SetTextMatrix(10, 0, 0, 10, 100, 100)
gstate = element.GetGState()
gstate.SetTextRenderMode(GState.e_fill_text)
gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
gstate.SetStrokeColor(ColorPt(1, 1, 1))
element.UpdateTextMetrics()
writer.WriteElement(element)
writer.WriteElement(eb.CreateTextEnd())
writer.End()
from core.helpers import ensure_dir
ensure_dir(output_filename)
doc.Save(output_filename, SDFDoc.e_linearized)
doc.Close()
我无法弄清楚的是:
/ EDIT2
答案 0 :(得分:2)
基于上面的代码,您似乎希望根据页面上第一个单词使用的字体样式(字体名称+颜色)将某些文本附加到现有页面。
上述代码存在一些问题。您正在设置笔触颜色而不是填充:
gstate.SetTextRenderMode(GState.e_fill_text)
gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB());
gstate.SetStrokeColor(ColorPt(1, 1, 1))
尝试
gstate.SetTextRenderMode(GState.e_fill_text)
gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB());
gstate.SetFillColor(ColorPt(1, 0, 0)) // hardcode to red … for testing purposes only
主要问题很可能与字体处理有关。您正在劫持现有字体并假设此字体使用“标准编码”。但是,此字体可能不使用标准编码。此外,现有PDF中的字体通常是子设置的(这意味着该字体不包含完整的字形列表,但只包含文档中存在的字符引用)。因此,您可能会看到notdef或空格而不是预期的文本。这里和其他一些问题包含在这里:
https://groups.google.com/d/msg/pdfnet-sdk/RBTuJG2uILk/pGkrKnqZ_YIJ https://groups.google.com/d/msg/pdfnet-sdk/2y8s5aehq-c/xyknr9W5r-cJ
作为一种解决方案,您可以直接找到匹配的系统字体(例如,基于字体名称和其他属性),而不是直接使用嵌入字体,并创建新字体。 PDFNet提供了一种实用方法 Font.Create(doc, font) , or Font.Create(doc, "Font name")。
此方法将创建Unicode字体,因此您应该使用eb.CreateUnicodeTextRun()而不是eb.CreateTextRun()。
或者,您可以使用AcroForm作为模板(请参阅InteractiveForms示例)和pdfdoc.FattenAnnotations()以使用该文档的只读版本结束。