@@ -46,11 +46,17 @@ pub struct PixbufContainer {
4646 cached_clip_mask : Option < tiny_skia:: Mask > ,
4747 clip_mask_dirty : bool ,
4848 images : HashMap < String , tiny_skia:: Pixmap > ,
49+ pending_images : Vec < ( String , bool ) > ,
50+ /// URLs that have already been handed off for fetching. Prevents the same
51+ /// URL from being re-added to `pending_images` across document rebuilds.
52+ requested_images : std:: collections:: HashSet < String > ,
4953 viewport : Position ,
5054 base_url : String ,
5155 caption : String ,
5256 scale_factor : f32 ,
5357 ignore_overflow_clips : bool ,
58+ last_anchor_click : Option < String > ,
59+ current_cursor : String ,
5460}
5561
5662impl PixbufContainer {
@@ -82,6 +88,8 @@ impl PixbufContainer {
8288 cached_clip_mask : None ,
8389 clip_mask_dirty : false ,
8490 images : HashMap :: new ( ) ,
91+ pending_images : Vec :: new ( ) ,
92+ requested_images : std:: collections:: HashSet :: new ( ) ,
8593 viewport : Position {
8694 x : 0.0 ,
8795 y : 0.0 ,
@@ -92,6 +100,8 @@ impl PixbufContainer {
92100 caption : String :: new ( ) ,
93101 scale_factor,
94102 ignore_overflow_clips : false ,
103+ last_anchor_click : None ,
104+ current_cursor : String :: new ( ) ,
95105 }
96106 }
97107
@@ -170,6 +180,33 @@ impl PixbufContainer {
170180 self . ignore_overflow_clips = ignore;
171181 }
172182
183+ /// Take the last anchor click URL, if any.
184+ ///
185+ /// Returns `Some(url)` when `on_anchor_click` was triggered by litehtml
186+ /// (via `Document::on_lbutton_up`), clearing the stored value.
187+ pub fn take_anchor_click ( & mut self ) -> Option < String > {
188+ self . last_anchor_click . take ( )
189+ }
190+
191+ /// Drain and return image URLs discovered during layout that haven't been
192+ /// loaded yet. The consumer is responsible for fetching the data and calling
193+ /// `load_image_data` with the result.
194+ pub fn take_pending_images ( & mut self ) -> Vec < ( String , bool ) > {
195+ std:: mem:: take ( & mut self . pending_images )
196+ }
197+
198+ /// Clear all pending/requested image tracking. Call on navigation so
199+ /// the new page's images are discovered fresh.
200+ pub fn clear_pending_images ( & mut self ) {
201+ self . pending_images . clear ( ) ;
202+ self . requested_images . clear ( ) ;
203+ }
204+
205+ /// Get the current CSS cursor value set by litehtml (e.g. `"pointer"`, `"default"`).
206+ pub fn cursor ( & self ) -> & str {
207+ & self . current_cursor
208+ }
209+
173210 /// Resize the pixmap, clearing all existing content.
174211 pub fn resize ( & mut self , width : u32 , height : u32 ) {
175212 self . resize_with_scale ( width, height, self . scale_factor ) ;
@@ -739,8 +776,13 @@ impl DocumentContainer for PixbufContainer {
739776 width : 1.0 ,
740777 ..Stroke :: default ( )
741778 } ;
742- self . pixmap
743- . stroke_path ( & path, & paint, & stroke, transform, self . cached_clip_mask . as_ref ( ) ) ;
779+ self . pixmap . stroke_path (
780+ & path,
781+ & paint,
782+ & stroke,
783+ transform,
784+ self . cached_clip_mask . as_ref ( ) ,
785+ ) ;
744786 }
745787 }
746788 2 => {
@@ -756,8 +798,12 @@ impl DocumentContainer for PixbufContainer {
756798 }
757799 }
758800
759- fn load_image ( & mut self , _src : & str , _baseurl : & str , _redraw_on_ready : bool ) {
760- // Image loading is handled externally via `load_image_data`.
801+ fn load_image ( & mut self , src : & str , _baseurl : & str , redraw_on_ready : bool ) {
802+ if src. is_empty ( ) || self . images . contains_key ( src) || self . requested_images . contains ( src) {
803+ return ;
804+ }
805+ self . requested_images . insert ( src. to_string ( ) ) ;
806+ self . pending_images . push ( ( src. to_string ( ) , redraw_on_ready) ) ;
761807 }
762808
763809 fn get_image_size ( & self , src : & str , _baseurl : & str ) -> Size {
@@ -807,14 +853,22 @@ impl DocumentContainer for PixbufContainer {
807853 intersect_masks ( & mut m, existing) ;
808854 }
809855 self . pixmap . draw_pixmap (
810- dst_x, dst_y, img. as_ref ( ) , & img_paint,
811- Transform :: identity ( ) , Some ( & m) ,
856+ dst_x,
857+ dst_y,
858+ img. as_ref ( ) ,
859+ & img_paint,
860+ Transform :: identity ( ) ,
861+ Some ( & m) ,
812862 ) ;
813863 }
814864 } else {
815865 self . pixmap . draw_pixmap (
816- dst_x, dst_y, img. as_ref ( ) , & img_paint,
817- Transform :: identity ( ) , self . cached_clip_mask . as_ref ( ) ,
866+ dst_x,
867+ dst_y,
868+ img. as_ref ( ) ,
869+ & img_paint,
870+ Transform :: identity ( ) ,
871+ self . cached_clip_mask . as_ref ( ) ,
818872 ) ;
819873 }
820874 }
@@ -832,8 +886,13 @@ impl DocumentContainer for PixbufContainer {
832886 if let Some ( path) =
833887 build_rounded_rect_path ( border. x , border. y , border. width , border. height , & radii)
834888 {
835- self . pixmap
836- . fill_path ( & path, & paint, FillRule :: Winding , transform, self . cached_clip_mask . as_ref ( ) ) ;
889+ self . pixmap . fill_path (
890+ & path,
891+ & paint,
892+ FillRule :: Winding ,
893+ transform,
894+ self . cached_clip_mask . as_ref ( ) ,
895+ ) ;
837896 }
838897 }
839898
@@ -878,8 +937,13 @@ impl DocumentContainer for PixbufContainer {
878937 if let Some ( path) =
879938 build_rounded_rect_path ( border. x , border. y , border. width , border. height , & radii)
880939 {
881- self . pixmap
882- . fill_path ( & path, & paint, FillRule :: Winding , transform, self . cached_clip_mask . as_ref ( ) ) ;
940+ self . pixmap . fill_path (
941+ & path,
942+ & paint,
943+ FillRule :: Winding ,
944+ transform,
945+ self . cached_clip_mask . as_ref ( ) ,
946+ ) ;
883947 }
884948 }
885949 }
@@ -930,8 +994,13 @@ impl DocumentContainer for PixbufContainer {
930994 if let Some ( path) =
931995 build_rounded_rect_path ( border. x , border. y , border. width , border. height , & radii)
932996 {
933- self . pixmap
934- . fill_path ( & path, & paint, FillRule :: Winding , transform, self . cached_clip_mask . as_ref ( ) ) ;
997+ self . pixmap . fill_path (
998+ & path,
999+ & paint,
1000+ FillRule :: Winding ,
1001+ transform,
1002+ self . cached_clip_mask . as_ref ( ) ,
1003+ ) ;
9351004 }
9361005 }
9371006 }
@@ -1016,9 +1085,13 @@ impl DocumentContainer for PixbufContainer {
10161085 self . base_url = base_url. to_string ( ) ;
10171086 }
10181087
1019- fn on_anchor_click ( & mut self , _url : & str ) { }
1088+ fn on_anchor_click ( & mut self , url : & str ) {
1089+ self . last_anchor_click = Some ( url. to_string ( ) ) ;
1090+ }
10201091
1021- fn set_cursor ( & mut self , _cursor : & str ) { }
1092+ fn set_cursor ( & mut self , cursor : & str ) {
1093+ self . current_cursor = cursor. to_string ( ) ;
1094+ }
10221095
10231096 fn set_clip ( & mut self , pos : Position , radius : BorderRadiuses ) {
10241097 if self . ignore_overflow_clips {
@@ -1100,13 +1173,13 @@ fn blend_pixel(
11001173 }
11011174
11021175 // Apply clip mask
1176+ let pixel_offset = y as usize * width as usize + x as usize ;
11031177 let effective_a = if let Some ( mask) = mask {
1104- let mask_idx = ( y * width + x) as usize ;
11051178 let mask_data = mask. data ( ) ;
1106- if mask_idx >= mask_data. len ( ) {
1179+ if pixel_offset >= mask_data. len ( ) {
11071180 return ;
11081181 }
1109- let mask_val = mask_data[ mask_idx ] ;
1182+ let mask_val = mask_data[ pixel_offset ] ;
11101183 if mask_val == 0 {
11111184 return ;
11121185 }
@@ -1119,7 +1192,7 @@ fn blend_pixel(
11191192 return ;
11201193 }
11211194
1122- let idx = ( ( y * width + x ) * 4 ) as usize ;
1195+ let idx = pixel_offset * 4 ;
11231196 if idx + 3 >= data. len ( ) {
11241197 return ;
11251198 }
0 commit comments