@@ -230,20 +230,65 @@ def _datetime_to_pdf(d):
230
230
return r
231
231
232
232
233
- def _get_link_annotation (gc , x , y , width , height ):
233
+ def _calculate_quad_point_coordinates (x , y , width , height , angle = 0 ):
234
+ """
235
+ Calculate the coordinates of rectangle when rotated by angle around x, y
236
+ """
237
+
238
+ angle = math .radians (- angle )
239
+ sin_angle = math .sin (angle )
240
+ cos_angle = math .cos (angle )
241
+ a = x + height * sin_angle
242
+ b = y + height * cos_angle
243
+ c = x + width * cos_angle + height * sin_angle
244
+ d = y - width * sin_angle + height * cos_angle
245
+ e = x + width * cos_angle
246
+ f = y - width * sin_angle
247
+ return ((x , y ), (e , f ), (c , d ), (a , b ))
248
+
249
+
250
+ def _get_coordinates_of_block (x , y , width , height , angle = 0 ):
251
+ """
252
+ Get the coordinates of rotated rectangle and rectangle that covers the
253
+ rotated rectangle.
254
+ """
255
+
256
+ vertices = _calculate_quad_point_coordinates (x , y , width ,
257
+ height , angle )
258
+
259
+ # Find min and max values for rectangle
260
+ # adjust so that QuadPoints is inside Rect
261
+ # PDF docs says that QuadPoints should be ignored if any point lies
262
+ # outside Rect, but for Acrobat it is enough that QuadPoints is on the
263
+ # border of Rect.
264
+
265
+ pad = 0.00001 if angle % 90 else 0
266
+ min_x = min (v [0 ] for v in vertices ) - pad
267
+ min_y = min (v [1 ] for v in vertices ) - pad
268
+ max_x = max (v [0 ] for v in vertices ) + pad
269
+ max_y = max (v [1 ] for v in vertices ) + pad
270
+ return (tuple (itertools .chain .from_iterable (vertices )),
271
+ (min_x , min_y , max_x , max_y ))
272
+
273
+
274
+ def _get_link_annotation (gc , x , y , width , height , angle = 0 ):
234
275
"""
235
276
Create a link annotation object for embedding URLs.
236
277
"""
278
+ quadpoints , rect = _get_coordinates_of_block (x , y , width , height , angle )
237
279
link_annotation = {
238
280
'Type' : Name ('Annot' ),
239
281
'Subtype' : Name ('Link' ),
240
- 'Rect' : ( x , y , x + width , y + height ) ,
282
+ 'Rect' : rect ,
241
283
'Border' : [0 , 0 , 0 ],
242
284
'A' : {
243
285
'S' : Name ('URI' ),
244
286
'URI' : gc .get_url (),
245
287
},
246
288
}
289
+ if angle % 90 :
290
+ # Add QuadPoints
291
+ link_annotation ['QuadPoints' ] = quadpoints
247
292
return link_annotation
248
293
249
294
@@ -2162,7 +2207,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
2162
2207
2163
2208
if gc .get_url () is not None :
2164
2209
self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2165
- gc , x , y , width , height ))
2210
+ gc , x , y , width , height , angle ))
2166
2211
2167
2212
fonttype = mpl .rcParams ['pdf.fonttype' ]
2168
2213
@@ -2219,7 +2264,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None):
2219
2264
2220
2265
if gc .get_url () is not None :
2221
2266
self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2222
- gc , x , y , page .width , page .height ))
2267
+ gc , x , y , page .width , page .height , angle ))
2223
2268
2224
2269
# Gather font information and do some setup for combining
2225
2270
# characters into strings. The variable seq will contain a
@@ -2320,7 +2365,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
2320
2365
font .set_text (s )
2321
2366
width , height = font .get_width_height ()
2322
2367
self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2323
- gc , x , y , width / 64 , height / 64 ))
2368
+ gc , x , y , width / 64 , height / 64 , angle ))
2324
2369
2325
2370
# If fonttype is neither 3 nor 42, emit the whole string at once
2326
2371
# without manual kerning.
0 commit comments