@@ -230,32 +230,54 @@ def _datetime_to_pdf(d):
230
230
return r
231
231
232
232
233
- def _calculate_quad_point_coordinates (x , y , width , height , angle = 0 ):
233
+ def _calculate_rotated_quad_point_coordinates (x , y , width , height , angle ):
234
234
"""
235
235
Calculate the coordinates of rectangle when rotated by angle around x, y
236
236
"""
237
237
238
- angle = math .radians (- angle )
238
+ angle = math .radians (angle )
239
239
sin_angle = math .sin (angle )
240
240
cos_angle = math .cos (angle )
241
- a = x + height * sin_angle
241
+ width_cos = width * cos_angle
242
+ width_sin = width * sin_angle
243
+ a = x - height * sin_angle
242
244
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
245
+ c = a + width_cos
246
+ d = b + width_sin
247
+ e = x + width_cos
248
+ f = y + width_sin
247
249
return ((x , y ), (e , f ), (c , d ), (a , b ))
248
250
249
251
250
- def _get_coordinates_of_block (x , y , width , height , angle = 0 ):
252
+ def _calculate_transformed_quad_point_coordinates (x , y , trans ):
251
253
"""
252
- Get the coordinates of rotated rectangle and rectangle that covers the
253
- rotated rectangle.
254
+ Calculate the coordinates of rectangle when rotated by angle around x, y
255
+ """
256
+ tr1 , tr2 , tr3 , tr4 , tr5 , tr6 = trans
257
+ width = 1
258
+ height = 1
259
+ a = x + 0 * tr1 + height * tr3 + tr5
260
+ b = y + 0 * tr2 + height * tr4 + tr6
261
+ c = x + width * tr1 + height * tr3 + tr5
262
+ d = y + width * tr2 + height * tr4 + tr6
263
+ e = x + width * tr1 + 0 * tr3 + tr5
264
+ f = y + width * tr2 + 0 * tr4 + tr6
265
+ return (((x + tr5 , y + tr6 ), (e , f ), (c , d ), (a , b )),
266
+ (0 if math .isclose (tr2 , 0 ) else 45 ))
267
+
268
+
269
+ def _get_coordinates_of_block (x , y , width , height , angle , trans ):
270
+ """
271
+ Get the coordinates of rotated or transformed rectangle and rectangle
272
+ that covers the rotated or transformed rectangle.
254
273
"""
255
274
256
- vertices = _calculate_quad_point_coordinates (x , y , width ,
257
- height , angle )
258
-
275
+ if trans is None :
276
+ vertices = _calculate_rotated_quad_point_coordinates (x , y , width ,
277
+ height , angle )
278
+ else :
279
+ vertices , angle = _calculate_transformed_quad_point_coordinates (x , y ,
280
+ trans )
259
281
# Find min and max values for rectangle
260
282
# adjust so that QuadPoints is inside Rect
261
283
# PDF docs says that QuadPoints should be ignored if any point lies
@@ -268,27 +290,29 @@ def _get_coordinates_of_block(x, y, width, height, angle=0):
268
290
max_x = max (v [0 ] for v in vertices ) + pad
269
291
max_y = max (v [1 ] for v in vertices ) + pad
270
292
return (tuple (itertools .chain .from_iterable (vertices )),
271
- (min_x , min_y , max_x , max_y ))
293
+ (min_x , min_y , max_x , max_y ), angle )
272
294
273
295
274
- def _get_link_annotation (gc , x , y , width , height , angle = 0 ):
296
+ def _get_link_annotation (gc , x , y , width , height , angle = 0 , trans = None ):
275
297
"""
276
298
Create a link annotation object for embedding URLs.
277
299
"""
278
- quadpoints , rect = _get_coordinates_of_block (x , y , width , height , angle )
279
300
link_annotation = {
280
301
'Type' : Name ('Annot' ),
281
302
'Subtype' : Name ('Link' ),
282
- 'Rect' : rect ,
283
303
'Border' : [0 , 0 , 0 ],
284
304
'A' : {
285
305
'S' : Name ('URI' ),
286
306
'URI' : gc .get_url (),
287
307
},
288
308
}
309
+ quadpoints , rect , angle = _get_coordinates_of_block (x , y , width , height ,
310
+ angle , trans )
311
+ link_annotation ['Rect' ] = rect
289
312
if angle % 90 :
290
313
# Add QuadPoints
291
314
link_annotation ['QuadPoints' ] = quadpoints
315
+
292
316
return link_annotation
293
317
294
318
@@ -2012,21 +2036,24 @@ def draw_image(self, gc, x, y, im, transform=None):
2012
2036
2013
2037
self .check_gc (gc )
2014
2038
2015
- w = 72.0 * w / self .image_dpi
2016
- h = 72.0 * h / self .image_dpi
2017
-
2018
2039
imob = self .file .imageObject (im )
2019
2040
2020
2041
if transform is None :
2042
+ w = 72.0 * w / self .image_dpi
2043
+ h = 72.0 * h / self .image_dpi
2044
+ if gc .get_url () is not None :
2045
+ self ._add_link_annotation (gc , x , y , w , h )
2021
2046
self .file .output (Op .gsave ,
2022
2047
w , 0 , 0 , h , x , y , Op .concat_matrix ,
2023
2048
imob , Op .use_xobject , Op .grestore )
2024
2049
else :
2025
- tr1 , tr2 , tr3 , tr4 , tr5 , tr6 = transform .frozen ().to_values ()
2050
+ trans = transform .frozen ().to_values ()
2051
+ if gc .get_url () is not None :
2052
+ self ._add_link_annotation (gc , x , y , w , h , trans = trans )
2026
2053
2027
2054
self .file .output (Op .gsave ,
2028
2055
1 , 0 , 0 , 1 , x , y , Op .concat_matrix ,
2029
- tr1 , tr2 , tr3 , tr4 , tr5 , tr6 , Op .concat_matrix ,
2056
+ * trans , Op .concat_matrix ,
2030
2057
imob , Op .use_xobject , Op .grestore )
2031
2058
2032
2059
def draw_path (self , gc , path , transform , rgbFace = None ):
@@ -2038,6 +2065,11 @@ def draw_path(self, gc, path, transform, rgbFace=None):
2038
2065
gc .get_sketch_params ())
2039
2066
self .file .output (self .gc .paint ())
2040
2067
2068
+ def _add_link_annotation (self , gc , x , y , width , height , angle = 0 ,
2069
+ trans = None ):
2070
+ self .file ._annotations [- 1 ][1 ].append (
2071
+ _get_link_annotation (gc , x , y , width , height , angle , trans ))
2072
+
2041
2073
def draw_path_collection (self , gc , master_transform , paths , all_transforms ,
2042
2074
offsets , offsetTrans , facecolors , edgecolors ,
2043
2075
linewidths , linestyles , antialiaseds , urls ,
@@ -2206,8 +2238,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
2206
2238
self ._text2path .mathtext_parser .parse (s , 72 , prop )
2207
2239
2208
2240
if gc .get_url () is not None :
2209
- self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2210
- gc , x , y , width , height , angle ))
2241
+ self ._add_link_annotation (gc , x , y , width , height , angle )
2211
2242
2212
2243
fonttype = mpl .rcParams ['pdf.fonttype' ]
2213
2244
@@ -2263,8 +2294,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None):
2263
2294
page , = dvi
2264
2295
2265
2296
if gc .get_url () is not None :
2266
- self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2267
- gc , x , y , page .width , page .height , angle ))
2297
+ self ._add_link_annotation (gc , x , y , page .width , page .height , angle )
2268
2298
2269
2299
# Gather font information and do some setup for combining
2270
2300
# characters into strings. The variable seq will contain a
@@ -2364,8 +2394,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
2364
2394
if gc .get_url () is not None :
2365
2395
font .set_text (s )
2366
2396
width , height = font .get_width_height ()
2367
- self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2368
- gc , x , y , width / 64 , height / 64 , angle ))
2397
+ self ._add_link_annotation (gc , x , y , width / 64 , height / 64 , angle )
2369
2398
2370
2399
# If fonttype is neither 3 nor 42, emit the whole string at once
2371
2400
# without manual kerning.
0 commit comments