@@ -27,29 +27,39 @@ subroutine render_figure_annotations(backend, annotations, annotation_count, &
2727 margin_left , margin_right , &
2828 margin_bottom , margin_top )
2929 ! ! Render all annotations for the current figure
30- ! !
30+ ! !
3131 ! ! This is the main entry point called from figure_render() that processes
3232 ! ! all stored annotations and dispatches them to the appropriate backend.
3333 ! ! Uses existing backend text rendering infrastructure.
34-
34+
35+ use fortplot_pdf, only: pdf_context
36+
3537 class(plot_context), intent (inout ) :: backend
3638 type (text_annotation_t), intent (in ) :: annotations(:)
3739 integer , intent (in ) :: annotation_count
3840 real (wp), intent (in ) :: x_min, x_max, y_min, y_max
3941 integer , intent (in ) :: width, height
4042 real (wp), intent (in ) :: margin_left, margin_right, margin_bottom, margin_top
41-
43+
4244 integer :: i
4345 real (wp) :: render_x, render_y
44- logical :: valid_annotation
46+ logical :: valid_annotation, is_pdf_backend
4547 character (len= 256 ) :: error_message
46-
48+
4749 ! Early exit if no annotations
4850 if (annotation_count == 0 ) return
49-
51+
52+ ! Check if backend is PDF (PDF expects data coordinates, not pixels)
53+ select type (backend)
54+ type is (pdf_context)
55+ is_pdf_backend = .true.
56+ class default
57+ is_pdf_backend = .false.
58+ end select
59+
5060 call log_info(" Rendering annotations: processing " // &
5161 trim (adjustl (int_to_char(annotation_count))) // " annotations" )
52-
62+
5363 ! Process each annotation
5464 do i = 1 , annotation_count
5565 ! Skip re-validation if already validated at creation time (Issue #870: prevent duplicate warnings)
@@ -68,21 +78,45 @@ subroutine render_figure_annotations(backend, annotations, annotation_count, &
6878 cycle
6979 end if
7080 end if
71-
81+
7282 ! Skip pie chart label/autopct annotations for ASCII and PDF backends
7383 ! ASCII backend uses legend-only approach for cleaner output
7484 ! PDF backend has coordinate transformation issues with pie annotations
7585 if (should_skip_pie_annotation(backend, annotations(i))) then
7686 cycle
7787 end if
78-
79- ! Transform coordinates to rendering coordinates
80- call transform_annotation_to_rendering_coords(annotations(i), &
81- x_min, x_max, y_min, y_max, &
82- width, height, &
83- margin_left, margin_right, &
84- margin_bottom, margin_top, &
85- render_x, render_y)
88+
89+ ! PDF backend text() expects DATA coordinates and applies normalize_to_pdf_coords
90+ ! But annotations can be in FIGURE or AXIS coordinates, so we need special handling
91+ if (is_pdf_backend .and. annotations(i)% coord_type /= COORD_DATA) then
92+ ! For PDF with FIGURE/AXIS coordinates: convert to DATA coordinates first
93+ ! Then PDF's text() will apply normalize_to_pdf_coords
94+ select case (annotations(i)% coord_type)
95+ case (COORD_FIGURE)
96+ ! Figure coordinates (0-1): map to data space
97+ render_x = x_min + annotations(i)% x * (x_max - x_min)
98+ render_y = y_min + annotations(i)% y * (y_max - y_min)
99+ case (COORD_AXIS)
100+ ! Axis coordinates (0-1 in plot area): map to data space
101+ render_x = x_min + annotations(i)% x * (x_max - x_min)
102+ render_y = y_min + annotations(i)% y * (y_max - y_min)
103+ case default
104+ render_x = annotations(i)% x
105+ render_y = annotations(i)% y
106+ end select
107+ else if (is_pdf_backend) then
108+ ! PDF with DATA coordinates: pass directly (text() will transform)
109+ render_x = annotations(i)% x
110+ render_y = annotations(i)% y
111+ else
112+ ! For raster/ASCII: transform to pixel coordinates
113+ call transform_annotation_to_rendering_coords(annotations(i), &
114+ x_min, x_max, y_min, y_max, &
115+ width, height, &
116+ margin_left, margin_right, &
117+ margin_bottom, margin_top, &
118+ render_x, render_y)
119+ end if
86120
87121 ! Set annotation color
88122 call backend% color(annotations(i)% color(1 ), &
@@ -91,7 +125,7 @@ subroutine render_figure_annotations(backend, annotations, annotation_count, &
91125
92126 ! Render the annotation text using existing backend method
93127 call backend% text(render_x, render_y, trim (annotations(i)% text))
94-
128+
95129 ! Render arrow if present (simplified implementation)
96130 if (annotations(i)% has_arrow) then
97131 call render_annotation_arrow(backend, annotations(i), &
@@ -101,7 +135,7 @@ subroutine render_figure_annotations(backend, annotations, annotation_count, &
101135 margin_bottom, margin_top)
102136 end if
103137 end do
104-
138+
105139 call log_info(" Annotation rendering completed successfully" )
106140 end subroutine render_figure_annotations
107141
0 commit comments