@@ -230,20 +230,65 @@ def _datetime_to_pdf(d):
230230 return r
231231
232232
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 ):
234275 """
235276 Create a link annotation object for embedding URLs.
236277 """
278+ quadpoints , rect = _get_coordinates_of_block (x , y , width , height , angle )
237279 link_annotation = {
238280 'Type' : Name ('Annot' ),
239281 'Subtype' : Name ('Link' ),
240- 'Rect' : ( x , y , x + width , y + height ) ,
282+ 'Rect' : rect ,
241283 'Border' : [0 , 0 , 0 ],
242284 'A' : {
243285 'S' : Name ('URI' ),
244286 'URI' : gc .get_url (),
245287 },
246288 }
289+ if angle % 90 :
290+ # Add QuadPoints
291+ link_annotation ['QuadPoints' ] = quadpoints
247292 return link_annotation
248293
249294
@@ -2162,7 +2207,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
21622207
21632208 if gc .get_url () is not None :
21642209 self .file ._annotations [- 1 ][1 ].append (_get_link_annotation (
2165- gc , x , y , width , height ))
2210+ gc , x , y , width , height , angle ))
21662211
21672212 fonttype = mpl .rcParams ['pdf.fonttype' ]
21682213
@@ -2219,7 +2264,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None):
22192264
22202265 if gc .get_url () is not None :
22212266 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 ))
22232268
22242269 # Gather font information and do some setup for combining
22252270 # 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):
23202365 font .set_text (s )
23212366 width , height = font .get_width_height ()
23222367 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 ))
23242369
23252370 # If fonttype is neither 3 nor 42, emit the whole string at once
23262371 # without manual kerning.
0 commit comments