Skip to main content

pdfkit/
view.rs

1use std::ptr;
2
3use crate::destination::PdfDestination;
4use crate::document::PdfDocument;
5use crate::error::Result;
6use crate::ffi;
7use crate::handle::ObjectHandle;
8use crate::page::PdfPage;
9use crate::page_overlay_view_provider::PdfPageOverlayViewProviderHandle;
10use crate::selection::PdfSelection;
11use crate::types::{
12    DisplayBox, PdfAreaOfInterest, PdfDisplayDirection, PdfDisplayMode, PdfPoint, PdfSize,
13    PdfViewInfo,
14};
15use crate::util::parse_json;
16use crate::view_delegate::PdfViewDelegateHandle;
17
18#[derive(Debug, Clone)]
19pub struct PdfView {
20    handle: ObjectHandle,
21}
22
23impl PdfView {
24    pub(crate) fn from_handle(handle: ObjectHandle) -> Self {
25        Self { handle }
26    }
27
28    pub fn new(size: PdfSize) -> Result<Self> {
29        let mut out_view = ptr::null_mut();
30        let mut out_error = ptr::null_mut();
31        let status =
32            unsafe { ffi::pdf_view_new(size.width, size.height, &mut out_view, &mut out_error) };
33        crate::util::status_result(status, out_error)?;
34        Ok(Self::from_handle(crate::util::required_handle(
35            out_view, "PDFView",
36        )?))
37    }
38
39    pub fn info(&self) -> Result<PdfViewInfo> {
40        parse_json(
41            unsafe { ffi::pdf_view_info_json(self.handle.as_ptr()) },
42            "PDFView",
43        )
44    }
45
46    #[must_use]
47    pub fn document(&self) -> Option<PdfDocument> {
48        let ptr = unsafe { ffi::pdf_view_document(self.handle.as_ptr()) };
49        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfDocument::from_handle)
50    }
51
52    pub fn set_document(&self, document: Option<&PdfDocument>) -> Result<()> {
53        let mut out_error = ptr::null_mut();
54        let status = unsafe {
55            ffi::pdf_view_set_document(
56                self.handle.as_ptr(),
57                document.map_or(ptr::null_mut(), PdfDocument::as_handle_ptr),
58                &mut out_error,
59            )
60        };
61        crate::util::status_result(status, out_error)
62    }
63
64    pub fn set_delegate(&self, delegate: Option<&PdfViewDelegateHandle>) -> Result<()> {
65        let mut out_error = ptr::null_mut();
66        let status = unsafe {
67            ffi::pdf_view_set_delegate(
68                self.handle.as_ptr(),
69                delegate.map_or(ptr::null_mut(), PdfViewDelegateHandle::as_handle_ptr),
70                &mut out_error,
71            )
72        };
73        crate::util::status_result(status, out_error)
74    }
75
76    pub fn set_page_overlay_view_provider(
77        &self,
78        provider: Option<&PdfPageOverlayViewProviderHandle>,
79    ) -> Result<()> {
80        let mut out_error = ptr::null_mut();
81        let status = unsafe {
82            ffi::pdf_view_set_page_overlay_view_provider(
83                self.handle.as_ptr(),
84                provider.map_or(
85                    ptr::null_mut(),
86                    PdfPageOverlayViewProviderHandle::as_handle_ptr,
87                ),
88                &mut out_error,
89            )
90        };
91        crate::util::status_result(status, out_error)
92    }
93
94    #[must_use]
95    pub fn current_page(&self) -> Option<PdfPage> {
96        let ptr = unsafe { ffi::pdf_view_current_page(self.handle.as_ptr()) };
97        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfPage::from_handle)
98    }
99
100    #[must_use]
101    pub fn current_destination(&self) -> Option<PdfDestination> {
102        let ptr = unsafe { ffi::pdf_view_current_destination(self.handle.as_ptr()) };
103        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfDestination::from_handle)
104    }
105
106    #[must_use]
107    pub fn current_selection(&self) -> Option<PdfSelection> {
108        let ptr = unsafe { ffi::pdf_view_current_selection(self.handle.as_ptr()) };
109        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfSelection::from_handle)
110    }
111
112    pub fn set_current_selection(
113        &self,
114        selection: Option<&PdfSelection>,
115        animate: bool,
116    ) -> Result<()> {
117        let mut out_error = ptr::null_mut();
118        let status = unsafe {
119            ffi::pdf_view_set_current_selection(
120                self.handle.as_ptr(),
121                selection.map_or(ptr::null_mut(), PdfSelection::as_handle_ptr),
122                i32::from(animate),
123                &mut out_error,
124            )
125        };
126        crate::util::status_result(status, out_error)
127    }
128
129    pub fn clear_selection(&self) {
130        unsafe { ffi::pdf_view_clear_selection(self.handle.as_ptr()) };
131    }
132
133    pub fn go_to_page(&self, page: &PdfPage) -> Result<()> {
134        let mut out_error = ptr::null_mut();
135        let status = unsafe {
136            ffi::pdf_view_go_to_page(self.handle.as_ptr(), page.as_handle_ptr(), &mut out_error)
137        };
138        crate::util::status_result(status, out_error)
139    }
140
141    pub fn go_to_destination(&self, destination: &PdfDestination) -> Result<()> {
142        let mut out_error = ptr::null_mut();
143        let status = unsafe {
144            ffi::pdf_view_go_to_destination(
145                self.handle.as_ptr(),
146                destination.as_handle_ptr(),
147                &mut out_error,
148            )
149        };
150        crate::util::status_result(status, out_error)
151    }
152
153    pub fn go_to_selection(&self, selection: &PdfSelection) -> Result<()> {
154        let mut out_error = ptr::null_mut();
155        let status = unsafe {
156            ffi::pdf_view_go_to_selection(
157                self.handle.as_ptr(),
158                selection.as_handle_ptr(),
159                &mut out_error,
160            )
161        };
162        crate::util::status_result(status, out_error)
163    }
164
165    pub fn set_display_mode(&self, mode: PdfDisplayMode) -> Result<()> {
166        let mut out_error = ptr::null_mut();
167        let status = unsafe {
168            ffi::pdf_view_set_display_mode(self.handle.as_ptr(), mode as i32, &mut out_error)
169        };
170        crate::util::status_result(status, out_error)
171    }
172
173    pub fn set_display_direction(&self, direction: PdfDisplayDirection) -> Result<()> {
174        let mut out_error = ptr::null_mut();
175        let status = unsafe {
176            ffi::pdf_view_set_display_direction(
177                self.handle.as_ptr(),
178                direction as i32,
179                &mut out_error,
180            )
181        };
182        crate::util::status_result(status, out_error)
183    }
184
185    pub fn set_display_box(&self, display_box: DisplayBox) -> Result<()> {
186        let mut out_error = ptr::null_mut();
187        let status = unsafe {
188            ffi::pdf_view_set_display_box(
189                self.handle.as_ptr(),
190                display_box.as_raw(),
191                &mut out_error,
192            )
193        };
194        crate::util::status_result(status, out_error)
195    }
196
197    pub fn set_auto_scales(&self, value: bool) {
198        unsafe { ffi::pdf_view_set_auto_scales(self.handle.as_ptr(), i32::from(value)) };
199    }
200
201    pub fn set_scale_factor(&self, value: f64) {
202        unsafe { ffi::pdf_view_set_scale_factor(self.handle.as_ptr(), value) };
203    }
204
205    pub fn set_min_scale_factor(&self, value: f64) {
206        unsafe { ffi::pdf_view_set_min_scale_factor(self.handle.as_ptr(), value) };
207    }
208
209    pub fn set_max_scale_factor(&self, value: f64) {
210        unsafe { ffi::pdf_view_set_max_scale_factor(self.handle.as_ptr(), value) };
211    }
212
213    pub fn layout_document_view(&self) {
214        unsafe { ffi::pdf_view_layout_document_view(self.handle.as_ptr()) };
215    }
216
217    #[must_use]
218    pub fn area_of_interest_for_point(&self, point: PdfPoint) -> PdfAreaOfInterest {
219        PdfAreaOfInterest::from_bits(unsafe {
220            ffi::pdf_view_area_of_interest_for_point(self.handle.as_ptr(), point.x, point.y)
221        })
222    }
223
224    #[must_use]
225    pub fn visible_page_count(&self) -> usize {
226        unsafe { ffi::pdf_view_visible_page_count(self.handle.as_ptr()) as usize }
227    }
228
229    #[must_use]
230    pub fn visible_page(&self, index: usize) -> Option<PdfPage> {
231        let ptr = unsafe { ffi::pdf_view_visible_page_at(self.handle.as_ptr(), index as u64) };
232        unsafe { ObjectHandle::from_retained_ptr(ptr) }.map(PdfPage::from_handle)
233    }
234
235    #[must_use]
236    pub fn visible_pages(&self) -> Vec<PdfPage> {
237        (0..self.visible_page_count())
238            .filter_map(|index| self.visible_page(index))
239            .collect()
240    }
241
242    pub(crate) fn as_handle_ptr(&self) -> *mut core::ffi::c_void {
243        self.handle.as_ptr()
244    }
245}