PyMuPDF 1.24.4 中文文档(三)(3)https://developer.aliyun.com/article/1559532
使用按钮和 JavaScript
自 MuPDF v1.16 起,‘FreeText’ 注释不再支持 Times-Roman、Helvetica 或 Courier 字体的粗体或斜体版本。
衷心感谢我们的用户 @kurokawaikki,他为绕过此限制贡献了以下脚本。
""" Problem: Since MuPDF v1.16 a 'Freetext' annotation font is restricted to the "normal" versions (no bold, no italics) of Times-Roman, Helvetica, Courier. It is impossible to use PyMuPDF to modify this. Solution: Using Adobe's JavaScript API, it is possible to manipulate properties of Freetext annotations. Check out these references: https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf, or https://www.adobe.com/devnet/acrobat/documentation.html. Function 'this.getAnnots()' will return all annotations as an array. We loop over this array to set the properties of the text through the 'richContents' attribute. There is no explicit property to set text to bold, but it is possible to set fontWeight=800 (400 is the normal size) of richContents. Other attributes, like color, italics, etc. can also be set via richContents. If we have 'FreeText' annotations created with PyMuPDF, we can make use of this JavaScript feature to modify the font - thus circumventing the above restriction. Use PyMuPDF v1.16.12 to create a push button that executes a Javascript containing the desired code. This is what this program does. Then open the resulting file with Adobe reader (!). After clicking on the button, all Freetext annotations will be bold, and the file can be saved. If desired, the button can be removed again, using free tools like PyMuPDF or PDF XChange editor. Note / Caution: --------------- The JavaScript will **only** work if the file is opened with Adobe Acrobat reader! When using other PDF viewers, the reaction is unforeseeable. """ import sys import pymupdf # this JavaScript will execute when the button is clicked: jscript = """ var annt = this.getAnnots(); annt.forEach(function (item, index) { try { var span = item.richContents; span.forEach(function (it, dx) { it.fontWeight = 800; }) item.richContents = span; } catch (err) {} }); app.alert('Done'); """ i_fn = sys.argv[1] # input file name o_fn = "bold-" + i_fn # output filename doc = pymupdf.open(i_fn) # open input page = doc[0] # get desired page # ------------------------------------------------ # make a push button for invoking the JavaScript # ------------------------------------------------ widget = pymupdf.Widget() # create widget # make it a 'PushButton' widget.field_type = pymupdf.PDF_WIDGET_TYPE_BUTTON widget.field_flags = pymupdf.PDF_BTN_FIELD_IS_PUSHBUTTON widget.rect = pymupdf.Rect(5, 5, 20, 20) # button position widget.script = jscript # fill in JavaScript source text widget.field_name = "Make bold" # arbitrary name widget.field_value = "Off" # arbitrary value widget.fill_color = (0, 0, 1) # make button visible annot = page.add_widget(widget) # add the widget to the page doc.save(o_fn) # output the file
如何使用墨迹注释
墨迹注释用于包含手写涂鸦。一个典型的例子可能是包含名字和姓氏的签名图像。从技术上讲,墨迹注释实现为点列表的列表。每个点列表被视为连接点的连续线。不同的点列表表示注释的独立线段。
以下脚本创建了一个墨迹注释,其中包含两个数学曲线(正弦和余弦函数图形)作为线段:
import math import pymupdf #------------------------------------------------------------------------------ # preliminary stuff: create function value lists for sine and cosine #------------------------------------------------------------------------------ w360 = math.pi * 2 # go through full circle deg = w360 / 360 # 1 degree as radians rect = pymupdf.Rect(100,200, 300, 300) # use this rectangle first_x = rect.x0 # x starts from left first_y = rect.y0 + rect.height / 2. # rect middle means y = 0 x_step = rect.width / 360 # rect width means 360 degrees y_scale = rect.height / 2. # rect height means 2 sin_points = [] # sine values go here cos_points = [] # cosine values go here for x in range(362): # now fill in the values x_coord = x * x_step + first_x # current x coordinate y = -math.sin(x * deg) # sine p = (x_coord, y * y_scale + first_y) # corresponding point sin_points.append(p) # append y = -math.cos(x * deg) # cosine p = (x_coord, y * y_scale + first_y) # corresponding point cos_points.append(p) # append #------------------------------------------------------------------------------ # create the document with one page #------------------------------------------------------------------------------ doc = pymupdf.open() # make new PDF page = doc.new_page() # give it a page #------------------------------------------------------------------------------ # add the Ink annotation, consisting of 2 curve segments #------------------------------------------------------------------------------ annot = page.addInkAnnot((sin_points, cos_points)) # let it look a little nicer annot.set_border(width=0.3, dashes=[1,]) # line thickness, some dashing annot.set_colors(stroke=(0,0,1)) # make the lines blue annot.update() # update the appearance page.draw_rect(rect, width=0.3) # only to demonstrate we did OK doc.save("a-inktest.pdf")
这是结果:
对此页面有任何反馈吗?
此软件按原样提供,没有明示或默示的任何保证。此软件根据许可分发,并且未经明确授权不得复制、修改或分发。请参阅artifex.com上的许可信息或联系美国加利福尼亚州旧金山 Mesa 街 39 号 108A 室的 Artifex Software Inc. 了解更多信息。
此文档涵盖了所有版本直到 1.24.4。
## 如何添加和修改注释
在 PyMuPDF 中,可以通过 Page 方法添加新注释。一旦存在注释,可以使用 Annot 类的方法在很大程度上进行修改。
注释仅能插入 PDF 页面 - 其他文档类型不支持注释插入。
与许多其他工具相比,注释的初始插入具有最少的属性。我们将设置作者、创建日期或主题等属性留给程序员。
作为这些能力的概述,请查看以下脚本,它使用大多数可用的注释填充 PDF 页面。在下一节中查看更多特殊情况:
# -*- coding: utf-8 -*- """ ------------------------------------------------------------------------------- Demo script showing how annotations can be added to a PDF using PyMuPDF. It contains the following annotation types: Caret, Text, FreeText, text markers (underline, strike-out, highlight, squiggle), Circle, Square, Line, PolyLine, Polygon, FileAttachment, Stamp and Redaction. There is some effort to vary appearances by adding colors, line ends, opacity, rotation, dashed lines, etc. Dependencies ------------ PyMuPDF v1.17.0 ------------------------------------------------------------------------------- """ from __future__ import print_function import gc import sys import pymupdf print(pymupdf.__doc__) if pymupdf.VersionBind.split(".") < ["1", "17", "0"]: sys.exit("PyMuPDF v1.17.0+ is needed.") gc.set_debug(gc.DEBUG_UNCOLLECTABLE) highlight = "this text is highlighted" underline = "this text is underlined" strikeout = "this text is striked out" squiggled = "this text is zigzag-underlined" red = (1, 0, 0) blue = (0, 0, 1) gold = (1, 1, 0) green = (0, 1, 0) displ = pymupdf.Rect(0, 50, 0, 50) r = pymupdf.Rect(72, 72, 220, 100) t1 = u"têxt üsès Lätiñ charß,\nEUR: €, mu: µ, super scripts: ²³!" def print_descr(annot): """Print a short description to the right of each annot rect.""" annot.parent.insert_text( annot.rect.br + (10, -5), "%s annotation" % annot.type[1], color=red ) doc = pymupdf.open() page = doc.new_page() page.set_rotation(0) annot = page.add_caret_annot(r.tl) print_descr(annot) r = r + displ annot = page.add_freetext_annot( r, t1, fontsize=10, rotate=90, text_color=blue, fill_color=gold, align=pymupdf.TEXT_ALIGN_CENTER, ) annot.set_border(width=0.3, dashes=[2]) annot.update(text_color=blue, fill_color=gold) print_descr(annot) r = annot.rect + displ annot = page.add_text_annot(r.tl, t1) print_descr(annot) # Adding text marker annotations: # first insert a unique text, then search for it, then mark it pos = annot.rect.tl + displ.tl page.insert_text( pos, # insertion point highlight, # inserted text morph=(pos, pymupdf.Matrix(-5)), # rotate around insertion point ) rl = page.search_for(highlight, quads=True) # need a quad b/o tilted text annot = page.add_highlight_annot(rl[0]) print_descr(annot) pos = annot.rect.bl # next insertion point page.insert_text(pos, underline, morph=(pos, pymupdf.Matrix(-10))) rl = page.search_for(underline, quads=True) annot = page.add_underline_annot(rl[0]) print_descr(annot) pos = annot.rect.bl page.insert_text(pos, strikeout, morph=(pos, pymupdf.Matrix(-15))) rl = page.search_for(strikeout, quads=True) annot = page.add_strikeout_annot(rl[0]) print_descr(annot) pos = annot.rect.bl page.insert_text(pos, squiggled, morph=(pos, pymupdf.Matrix(-20))) rl = page.search_for(squiggled, quads=True) annot = page.add_squiggly_annot(rl[0]) print_descr(annot) pos = annot.rect.bl r = pymupdf.Rect(pos, pos.x + 75, pos.y + 35) + (0, 20, 0, 20) annot = page.add_polyline_annot([r.bl, r.tr, r.br, r.tl]) # 'Polyline' annot.set_border(width=0.3, dashes=[2]) annot.set_colors(stroke=blue, fill=green) annot.set_line_ends(pymupdf.PDF_ANNOT_LE_CLOSED_ARROW, pymupdf.PDF_ANNOT_LE_R_CLOSED_ARROW) annot.update(fill_color=(1, 1, 0)) print_descr(annot) r += displ annot = page.add_polygon_annot([r.bl, r.tr, r.br, r.tl]) # 'Polygon' annot.set_border(width=0.3, dashes=[2]) annot.set_colors(stroke=blue, fill=gold) annot.set_line_ends(pymupdf.PDF_ANNOT_LE_DIAMOND, pymupdf.PDF_ANNOT_LE_CIRCLE) annot.update() print_descr(annot) r += displ annot = page.add_line_annot(r.tr, r.bl) # 'Line' annot.set_border(width=0.3, dashes=[2]) annot.set_colors(stroke=blue, fill=gold) annot.set_line_ends(pymupdf.PDF_ANNOT_LE_DIAMOND, pymupdf.PDF_ANNOT_LE_CIRCLE) annot.update() print_descr(annot) r += displ annot = page.add_rect_annot(r) # 'Square' annot.set_border(width=1, dashes=[1, 2]) annot.set_colors(stroke=blue, fill=gold) annot.update(opacity=0.5) print_descr(annot) r += displ annot = page.add_circle_annot(r) # 'Circle' annot.set_border(width=0.3, dashes=[2]) annot.set_colors(stroke=blue, fill=gold) annot.update() print_descr(annot) r += displ annot = page.add_file_annot( r.tl, b"just anything for testing", "testdata.txt" # 'FileAttachment' ) print_descr(annot) # annot.rect r += displ annot = page.add_stamp_annot(r, stamp=10) # 'Stamp' annot.set_colors(stroke=green) annot.update() print_descr(annot) r += displ + (0, 0, 50, 10) rc = page.insert_textbox( r, "This content will be removed upon applying the redaction.", color=blue, align=pymupdf.TEXT_ALIGN_CENTER, ) annot = page.add_redact_annot(r) print_descr(annot) doc.save(__file__.replace(".py", "-%i.pdf" % page.rotation), deflate=True)
本脚本应导致以下输出:
如何使用自由文本
本脚本展示了处理“FreeText”注释的几种方法:
# -*- coding: utf-8 -*- import pymupdf # some colors blue = (0,0,1) green = (0,1,0) red = (1,0,0) gold = (1,1,0) # a new PDF with 1 page doc = pymupdf.open() page = doc.new_page() # 3 rectangles, same size, above each other r1 = pymupdf.Rect(100,100,200,150) r2 = r1 + (0,75,0,75) r3 = r2 + (0,75,0,75) # the text, Latin alphabet t = "¡Un pequeño texto para practicar!" # add 3 annots, modify the last one somewhat a1 = page.add_freetext_annot(r1, t, color=red) a2 = page.add_freetext_annot(r2, t, fontname="Ti", color=blue) a3 = page.add_freetext_annot(r3, t, fontname="Co", color=blue, rotate=90) a3.set_border(width=0) a3.update(fontsize=8, fill_color=gold) # save the PDF doc.save("a-freetext.pdf")
结果如下所示:
使用按钮和 JavaScript
自 MuPDF v1.16 版本起,“FreeText”注释不再支持 Times-Roman、Helvetica 或 Courier 字体的粗体或斜体版本。
特别感谢我们的用户@kurokawaikki,他贡献了以下脚本来绕过此限制。
""" Problem: Since MuPDF v1.16 a 'Freetext' annotation font is restricted to the "normal" versions (no bold, no italics) of Times-Roman, Helvetica, Courier. It is impossible to use PyMuPDF to modify this. Solution: Using Adobe's JavaScript API, it is possible to manipulate properties of Freetext annotations. Check out these references: https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf, or https://www.adobe.com/devnet/acrobat/documentation.html. Function 'this.getAnnots()' will return all annotations as an array. We loop over this array to set the properties of the text through the 'richContents' attribute. There is no explicit property to set text to bold, but it is possible to set fontWeight=800 (400 is the normal size) of richContents. Other attributes, like color, italics, etc. can also be set via richContents. If we have 'FreeText' annotations created with PyMuPDF, we can make use of this JavaScript feature to modify the font - thus circumventing the above restriction. Use PyMuPDF v1.16.12 to create a push button that executes a Javascript containing the desired code. This is what this program does. Then open the resulting file with Adobe reader (!). After clicking on the button, all Freetext annotations will be bold, and the file can be saved. If desired, the button can be removed again, using free tools like PyMuPDF or PDF XChange editor. Note / Caution: --------------- The JavaScript will **only** work if the file is opened with Adobe Acrobat reader! When using other PDF viewers, the reaction is unforeseeable. """ import sys import pymupdf # this JavaScript will execute when the button is clicked: jscript = """ var annt = this.getAnnots(); annt.forEach(function (item, index) { try { var span = item.richContents; span.forEach(function (it, dx) { it.fontWeight = 800; }) item.richContents = span; } catch (err) {} }); app.alert('Done'); """ i_fn = sys.argv[1] # input file name o_fn = "bold-" + i_fn # output filename doc = pymupdf.open(i_fn) # open input page = doc[0] # get desired page # ------------------------------------------------ # make a push button for invoking the JavaScript # ------------------------------------------------ widget = pymupdf.Widget() # create widget # make it a 'PushButton' widget.field_type = pymupdf.PDF_WIDGET_TYPE_BUTTON widget.field_flags = pymupdf.PDF_BTN_FIELD_IS_PUSHBUTTON widget.rect = pymupdf.Rect(5, 5, 20, 20) # button position widget.script = jscript # fill in JavaScript source text widget.field_name = "Make bold" # arbitrary name widget.field_value = "Off" # arbitrary value widget.fill_color = (0, 0, 1) # make button visible annot = page.add_widget(widget) # add the widget to the page doc.save(o_fn) # output the file
PyMuPDF 1.24.4 中文文档(三)(5)https://developer.aliyun.com/article/1559535