@@ -694,7 +694,13 @@ def __init__(self, filename, metadata=None):
694
694
695
695
self .paths = []
696
696
697
- self .pageAnnotations = [] # A list of annotations for the current page
697
+ # A list of annotations for each page. Each entry is a tuple of the
698
+ # overall Annots object reference that's inserted into the page object,
699
+ # followed by a list of the actual annotations.
700
+ self ._annotations = []
701
+ # For annotations added before a page is created; mostly for the
702
+ # purpose of newTextnote.
703
+ self .pageAnnotations = []
698
704
699
705
# The PDF spec recommends to include every procset
700
706
procsets = [Name (x ) for x in "PDF Text ImageB ImageC ImageI" .split ()]
@@ -720,6 +726,7 @@ def newPage(self, width, height):
720
726
721
727
self .width , self .height = width , height
722
728
contentObject = self .reserveObject ('page contents' )
729
+ annotsObject = self .reserveObject ('annotations' )
723
730
thePage = {'Type' : Name ('Page' ),
724
731
'Parent' : self .pagesObject ,
725
732
'Resources' : self .resourceObject ,
@@ -728,11 +735,12 @@ def newPage(self, width, height):
728
735
'Group' : {'Type' : Name ('Group' ),
729
736
'S' : Name ('Transparency' ),
730
737
'CS' : Name ('DeviceRGB' )},
731
- 'Annots' : self . pageAnnotations ,
738
+ 'Annots' : annotsObject ,
732
739
}
733
740
pageObject = self .reserveObject ('page' )
734
741
self .writeObject (pageObject , thePage )
735
742
self .pageList .append (pageObject )
743
+ self ._annotations .append ((annotsObject , self .pageAnnotations ))
736
744
737
745
self .beginStream (contentObject .id ,
738
746
self .reserveObject ('length of content stream' ))
@@ -750,14 +758,13 @@ def newTextnote(self, text, positionRect=[-100, -100, 0, 0]):
750
758
'Contents' : text ,
751
759
'Rect' : positionRect ,
752
760
}
753
- annotObject = self .reserveObject ('annotation' )
754
- self .writeObject (annotObject , theNote )
755
- self .pageAnnotations .append (annotObject )
761
+ self .pageAnnotations .append (theNote )
756
762
757
763
def finalize (self ):
758
764
"""Write out the various deferred objects and the pdf end matter."""
759
765
760
766
self .endStream ()
767
+ self ._write_annotations ()
761
768
self .writeFonts ()
762
769
self .writeExtGSTates ()
763
770
self ._write_soft_mask_groups ()
@@ -816,6 +823,10 @@ def endStream(self):
816
823
self .currentstream .end ()
817
824
self .currentstream = None
818
825
826
+ def _write_annotations (self ):
827
+ for annotsObject , annotations in self ._annotations :
828
+ self .writeObject (annotsObject , annotations )
829
+
819
830
def fontName (self , fontprop ):
820
831
"""
821
832
Select a font based on fontprop and return a name suitable for
@@ -2095,6 +2106,19 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
2095
2106
width , height , descent , glyphs , rects = \
2096
2107
self ._text2path .mathtext_parser .parse (s , 72 , prop )
2097
2108
2109
+ if gc .get_url () is not None :
2110
+ link_annotation = {
2111
+ 'Type' : Name ('Annot' ),
2112
+ 'Subtype' : Name ('Link' ),
2113
+ 'Rect' : (x , y , x + width , y + height ),
2114
+ 'Border' : [0 , 0 , 0 ],
2115
+ 'A' : {
2116
+ 'S' : Name ('URI' ),
2117
+ 'URI' : gc .get_url (),
2118
+ },
2119
+ }
2120
+ self .file ._annotations [- 1 ][1 ].append (link_annotation )
2121
+
2098
2122
global_fonttype = mpl .rcParams ['pdf.fonttype' ]
2099
2123
2100
2124
# Set up a global transformation matrix for the whole math expression
@@ -2151,6 +2175,19 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
2151
2175
with dviread .Dvi (dvifile , 72 ) as dvi :
2152
2176
page , = dvi
2153
2177
2178
+ if gc .get_url () is not None :
2179
+ link_annotation = {
2180
+ 'Type' : Name ('Annot' ),
2181
+ 'Subtype' : Name ('Link' ),
2182
+ 'Rect' : (x , y , x + page .width , y + page .height ),
2183
+ 'Border' : [0 , 0 , 0 ],
2184
+ 'A' : {
2185
+ 'S' : Name ('URI' ),
2186
+ 'URI' : gc .get_url (),
2187
+ },
2188
+ }
2189
+ self .file ._annotations [- 1 ][1 ].append (link_annotation )
2190
+
2154
2191
# Gather font information and do some setup for combining
2155
2192
# characters into strings. The variable seq will contain a
2156
2193
# sequence of font and text entries. A font entry is a list
@@ -2250,6 +2287,21 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
2250
2287
if is_opentype_cff_font (font .fname ):
2251
2288
fonttype = 42
2252
2289
2290
+ if gc .get_url () is not None :
2291
+ font .set_text (s )
2292
+ width , height = font .get_width_height ()
2293
+ link_annotation = {
2294
+ 'Type' : Name ('Annot' ),
2295
+ 'Subtype' : Name ('Link' ),
2296
+ 'Rect' : (x , y , x + width / 64 , y + height / 64 ),
2297
+ 'Border' : [0 , 0 , 0 ],
2298
+ 'A' : {
2299
+ 'S' : Name ('URI' ),
2300
+ 'URI' : gc .get_url (),
2301
+ },
2302
+ }
2303
+ self .file ._annotations [- 1 ][1 ].append (link_annotation )
2304
+
2253
2305
# If fonttype != 3 or there are no multibyte characters, emit the whole
2254
2306
# string at once.
2255
2307
if fonttype != 3 or all (ord (char ) <= 255 for char in s ):
0 commit comments